]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
CMP: add support for genm with crlStatusList and genp with crls
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Sat, 3 Dec 2022 16:49:08 +0000 (17:49 +0100)
committerTomas Mraz <tomas@openssl.org>
Wed, 1 May 2024 12:58:35 +0000 (14:58 +0200)
Introduce the capability to retrieve and update Certificate Revocation Lists
(CRLs) in the CMP client, as specified in section 4.3.4 of RFC 9483.

To request a CRL update, the CMP client can send a genm message with the
option -infotype crlStatusList. The server will respond with a genp message
containing the updated CRL, using the -infoType id-it-crls. The client can
then save the CRL in a specified file using the -crlout parameter.

Co-authored-by: Rajeev Ranjan <ranjan.rajeev@siemens.com>
Reviewed-by: Todd Short <todd.short@me.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23768)

27 files changed:
CHANGES.md
apps/cmp.c
apps/include/cmp_mock_srv.h
apps/lib/cmp_mock_srv.c
crypto/cmp/cmp_asn.c
crypto/cmp/cmp_err.c
crypto/cmp/cmp_genm.c
crypto/cmp/cmp_hdr.c
crypto/cmp/cmp_local.h
crypto/err/openssl.txt
crypto/x509/v3_crld.c
crypto/x509/v3_genn.c
doc/build.info
doc/man1/openssl-cmp.pod.in
doc/man3/GENERAL_NAME.pod [new file with mode: 0644]
doc/man3/OSSL_CMP_ITAV_new_caCerts.pod
doc/man3/OSSL_CMP_exec_certreq.pod
doc/man3/X509_dup.pod
include/openssl/cmp.h.in
include/openssl/cmperr.h
include/openssl/x509v3.h.in
test/recipes/80-test_cmp_http_data/Mock/newcrl.pem [new file with mode: 0644]
test/recipes/80-test_cmp_http_data/Mock/oldcrl.pem [new file with mode: 0644]
test/recipes/80-test_cmp_http_data/Mock/server.cnf
test/recipes/80-test_cmp_http_data/test_commands.csv
util/libcrypto.num
util/other.syms

index 28e1c0ae4d88f11cad2578cfb8999831fa00fbba..73587dc7325df91d9613bbc9aa4666282654dcce 100644 (file)
@@ -110,6 +110,10 @@ OpenSSL 3.3
 
     *Neil Horman*
 
+ * Added support for requesting CRL in CMP.
+
+    *Rajeev Ranjan, Siemens AG*
+
  * Added `-set_issuer` and `-set_subject` options to `openssl x509` to
    override the Issuer and Subject when creating a certificate. The `-subj`
    option now is an alias for `-set_subject`.
index 213596f723107272eed69f3f8327ad9c323bee17..407ee5ec32ec0b55fb50f7440c00e8d73c403e92 100644 (file)
@@ -94,6 +94,9 @@ static char *opt_oldwithold = NULL;
 static char *opt_newwithnew = NULL;
 static char *opt_newwithold = NULL;
 static char *opt_oldwithnew = NULL;
+static char *opt_crlcert = NULL;
+static char *opt_oldcrl = NULL;
+static char *opt_crlout = NULL;
 
 /* client authentication */
 static char *opt_ref = NULL;
@@ -143,6 +146,8 @@ static int opt_revreason = CRL_REASON_NONE;
 /* credentials format */
 static char *opt_certform_s = "PEM";
 static int opt_certform = FORMAT_PEM;
+static char *opt_crlform_s = "DER";
+static int opt_crlform = FORMAT_ASN1;
 static char *opt_keyform_s = NULL;
 static int opt_keyform = FORMAT_UNDEF;
 static char *opt_otherpass = NULL;
@@ -187,6 +192,7 @@ static char *opt_srv_trusted = NULL;
 static char *opt_srv_untrusted = NULL;
 static char *opt_ref_cert = NULL;
 static char *opt_rsp_cert = NULL;
+static char *opt_rsp_crl = NULL;
 static char *opt_rsp_extracerts = NULL;
 static char *opt_rsp_capubs = NULL;
 static char *opt_rsp_newwithnew = NULL;
@@ -237,12 +243,13 @@ typedef enum OPTION_choice {
     OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, OPT_NO_CACHE_EXTRACERTS,
     OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT,
     OPT_OLDWITHOLD, OPT_NEWWITHNEW, OPT_NEWWITHOLD, OPT_OLDWITHNEW,
+    OPT_CRLCERT, OPT_OLDCRL, OPT_CRLOUT,
 
     OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS,
     OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS,
     OPT_UNPROTECTED_REQUESTS,
 
-    OPT_CERTFORM, OPT_KEYFORM,
+    OPT_CERTFORM, OPT_CRLFORM, OPT_KEYFORM,
     OPT_OTHERPASS,
 #ifndef OPENSSL_NO_ENGINE
     OPT_ENGINE,
@@ -267,7 +274,7 @@ typedef enum OPTION_choice {
     OPT_SRV_REF, OPT_SRV_SECRET,
     OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
     OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
-    OPT_REF_CERT, OPT_RSP_CERT, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
+    OPT_REF_CERT, OPT_RSP_CERT, OPT_RSP_CRL, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
     OPT_RSP_NEWWITHNEW, OPT_RSP_NEWWITHOLD, OPT_RSP_OLDWITHNEW,
     OPT_POLL_COUNT, OPT_CHECK_AFTER,
     OPT_GRANT_IMPLICITCONF,
@@ -428,6 +435,12 @@ const OPTIONS cmp_options[] = {
       "File to save NewWithOld cert received in genp of type rootCaKeyUpdate"},
     { "oldwithnew", OPT_OLDWITHNEW, 's',
       "File to save OldWithNew cert received in genp of type rootCaKeyUpdate"},
+    { "crlcert", OPT_CRLCERT, 's',
+      "certificate to request a CRL for in genm of type crlStatusList"},
+    { "oldcrl", OPT_OLDCRL, 's',
+      "CRL to request update for in genm of type crlStatusList"},
+    { "crlout", OPT_CRLOUT, 's',
+      "File to save new CRL received in genp of type 'crls'"},
 
     OPT_SECTION("Client authentication"),
     {"ref", OPT_REF, 's',
@@ -459,6 +472,8 @@ const OPTIONS cmp_options[] = {
     OPT_SECTION("Credentials format"),
     {"certform", OPT_CERTFORM, 's',
      "Format (PEM or DER) to use when saving a certificate to a file. Default PEM"},
+    {"crlform", OPT_CRLFORM, 's',
+     "Format (PEM or DER) to use when saving a CRL to a file. Default DER"},
     {"keyform", OPT_KEYFORM, 's',
      "Format of the key input (ENGINE, other values ignored)"},
     {"otherpass", OPT_OTHERPASS, 's',
@@ -544,6 +559,8 @@ const OPTIONS cmp_options[] = {
      "Certificate to be expected for rr and any oldCertID in kur messages"},
     {"rsp_cert", OPT_RSP_CERT, 's',
      "Certificate to be returned as mock enrollment result"},
+    {"rsp_crl", OPT_RSP_CRL, 's',
+     "CRL to be returned in genp of type crls"},
     {"rsp_extracerts", OPT_RSP_EXTRACERTS, 's',
      "Extra certificates to be included in mock certification responses"},
     {"rsp_capubs", OPT_RSP_CAPUBS, 's',
@@ -623,13 +640,14 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {(char **)&opt_no_cache_extracerts},
     {&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout},
     {&opt_oldwithold}, {&opt_newwithnew}, {&opt_newwithold}, {&opt_oldwithnew},
+    {&opt_crlcert}, {&opt_oldcrl}, {&opt_crlout},
 
     {&opt_ref}, {&opt_secret},
     {&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass},
     {&opt_digest}, {&opt_mac}, {&opt_extracerts},
     {(char **)&opt_unprotected_requests},
 
-    {&opt_certform_s}, {&opt_keyform_s},
+    {&opt_certform_s}, {&opt_crlform_s}, {&opt_keyform_s},
     {&opt_otherpass},
 #ifndef OPENSSL_NO_ENGINE
     {&opt_engine},
@@ -652,7 +670,8 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {&opt_srv_ref}, {&opt_srv_secret},
     {&opt_srv_cert}, {&opt_srv_key}, {&opt_srv_keypass},
     {&opt_srv_trusted}, {&opt_srv_untrusted},
-    {&opt_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_extracerts}, {&opt_rsp_capubs},
+    {&opt_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_crl},
+    {&opt_rsp_extracerts}, {&opt_rsp_capubs},
     {&opt_rsp_newwithnew}, {&opt_rsp_newwithold}, {&opt_rsp_oldwithnew},
 
     {(char **)&opt_poll_count}, {(char **)&opt_check_after},
@@ -1010,6 +1029,19 @@ static int setup_certs(char *files, const char *desc, void *ctx,
     return ok;
 }
 
+static int setup_mock_crlout(void *ctx, const char *file, const char *desc)
+{
+    X509_CRL *crl;
+    int ok;
+
+    if (file == NULL)
+        return 1;
+    if ((crl = load_crl(file, FORMAT_UNDEF, 0, desc)) == NULL)
+        return 0;
+    ok = ossl_cmp_mock_srv_set1_crlOut(ctx, crl);
+    X509_CRL_free(crl);
+    return ok;
+}
 /*
  * parse and transform some options, checking their syntax.
  * Returns 1 on success, 0 on error
@@ -1057,6 +1089,11 @@ static int transform_opts(void)
         CMP_err("unknown option given for certificate storing format");
         return 0;
     }
+    if (opt_crlform_s != NULL
+            && !opt_format(opt_crlform_s, OPT_FMT_PEMDER, &opt_crlform)) {
+        CMP_err("unknown option given for CRL storing format");
+        return 0;
+    }
 
     return 1;
 }
@@ -1152,6 +1189,9 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
                         (add_X509_fn_t)ossl_cmp_mock_srv_set1_certOut))
             goto err;
     }
+    if (!setup_mock_crlout(srv_ctx, opt_rsp_crl,
+                           "CRL to be returned by the mock server"))
+        goto err;
     if (!setup_certs(opt_rsp_extracerts,
                      "CMP extra certificates for mock server", srv_ctx,
                      (add_X509_stack_fn_t)ossl_cmp_mock_srv_set1_chainOut))
@@ -2248,6 +2288,18 @@ static int write_cert(BIO *bio, X509 *cert)
     return 0;
 }
 
+static int write_crl(BIO *bio, X509_CRL *crl)
+{
+    if (opt_crlform != FORMAT_PEM && opt_crlform != FORMAT_ASN1) {
+        BIO_printf(bio_err, "error: unsupported type '%s' for writing CRLs\n",
+                   opt_crlform_s);
+        return 0;
+    }
+
+    return opt_crlform == FORMAT_PEM ? PEM_write_bio_X509_CRL(bio, crl)
+                                      : i2d_X509_CRL_bio(bio, crl);
+}
+
 /*
  * If file != NULL writes out a stack of certs to the given file.
  * If certs is NULL, the file is emptied.
@@ -2295,6 +2347,35 @@ static int save_free_certs(STACK_OF(X509) *certs,
     return n;
 }
 
+static int save_crl(X509_CRL *crl,
+                    const char *file, const char *desc)
+{
+    BIO *bio = NULL;
+    int res = 0;
+
+    if (file == NULL)
+        return 1;
+    if (crl != NULL)
+        CMP_info2("received %s, saving to file '%s'", desc, file);
+
+    if ((bio = BIO_new(BIO_s_file())) == NULL
+            || !BIO_write_filename(bio, (char *)file)) {
+        CMP_err2("could not open file '%s' for writing %s",
+                 file, desc);
+        goto end;
+    }
+
+    if (!write_crl(bio, crl)) {
+        CMP_err2("cannot write %s to file '%s'", desc, file);
+        goto end;
+    }
+    res = 1;
+
+ end:
+    BIO_free(bio);
+    return res;
+}
+
 static int delete_file(const char *file, const char *desc)
 {
     if (file == NULL)
@@ -2328,6 +2409,13 @@ static int save_cert_or_delete(X509 *cert, const char *file, const char *desc)
     }
 }
 
+static int save_crl_or_delete(X509_CRL *crl, const char *file, const char *desc)
+{
+    if (file == NULL)
+        return 1;
+    return (crl == NULL) ? delete_file(file, desc) : save_crl(crl, file, desc);
+}
+
 static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs)
 {
     int i, ret = 1;
@@ -2727,6 +2815,15 @@ static int get_opts(int argc, char **argv)
         case OPT_OLDWITHNEW:
             opt_oldwithnew = opt_str();
             break;
+        case OPT_CRLCERT:
+            opt_crlcert = opt_str();
+            break;
+        case OPT_OLDCRL:
+            opt_oldcrl = opt_str();
+            break;
+        case OPT_CRLOUT:
+            opt_crlout = opt_str();
+            break;
 
         case OPT_V_CASES:
             if (!opt_verify(o, vpm))
@@ -2822,6 +2919,9 @@ static int get_opts(int argc, char **argv)
         case OPT_CERTFORM:
             opt_certform_s = opt_str();
             break;
+        case OPT_CRLFORM:
+            opt_crlform_s = opt_str();
+            break;
         case OPT_KEYFORM:
             opt_keyform_s = opt_str();
             break;
@@ -2905,6 +3005,9 @@ static int get_opts(int argc, char **argv)
         case OPT_RSP_CERT:
             opt_rsp_cert = opt_str();
             break;
+        case OPT_RSP_CRL:
+            opt_rsp_crl = opt_str();
+            break;
         case OPT_RSP_EXTRACERTS:
             opt_rsp_extracerts = opt_str();
             break;
@@ -3141,6 +3244,58 @@ static int do_genm(OSSL_CMP_CTX *ctx)
     end_upd:
         X509_free(oldwithold);
         return res;
+    } else if (opt_infotype == NID_id_it_crlStatusList) {
+        X509_CRL *oldcrl = NULL, *crl = NULL;
+        X509 *crlcert = NULL;
+        int res = 0;
+        const char *desc = "CRL from genp of type 'crls'";
+
+        if (opt_oldcrl == NULL && opt_crlcert == NULL) {
+            CMP_err("Missing -oldcrl and no -crlcert given for -infotype crlStatusList");
+            return 0;
+        }
+        if (opt_crlout == NULL) {
+            CMP_err("Missing -crlout for -infotype crlStatusList");
+            return 0;
+        }
+
+        if (opt_crlcert != NULL) {
+            crlcert = load_cert_pwd(opt_crlcert, opt_otherpass,
+                                    "Cert for genm with -infotype crlStatusList");
+            if (crlcert == NULL)
+                goto end_crlupd;
+        }
+
+        if (opt_oldcrl != NULL) {
+            oldcrl = load_crl(opt_oldcrl, FORMAT_UNDEF, 0,
+                              "CRL for genm with -infotype crlStatusList");
+            if (oldcrl == NULL)
+                goto end_crlupd;
+        }
+
+        if (opt_oldcrl != NULL && opt_crlcert != NULL) {
+            if (X509_NAME_cmp(X509_CRL_get_issuer(oldcrl),
+                              X509_get_issuer_name(crlcert))
+                != 0)
+                CMP_warn("-oldcrl and -crlcert have different issuer");
+        }
+
+        if (!OSSL_CMP_get1_crlUpdate(ctx, crlcert, oldcrl, &crl))
+            goto end_crlupd;
+
+        if (crl == NULL)
+            CMP_info("no CRL update available");
+        if (!save_crl_or_delete(crl, opt_crlout, desc))
+            goto end_crlupd;
+
+        res = 1;
+
+    end_crlupd:
+        X509_free(crlcert);
+        X509_CRL_free(oldcrl);
+        X509_CRL_free(crl);
+        return res;
+
     } else {
         OSSL_CMP_ITAV *req;
         STACK_OF(OSSL_CMP_ITAV) *itavs;
index fcc1ef7bb4f0b3a079248d1b61039cbaa2a7b0e2..6b4290460aa6cc09f0205912e45ffc3bbe746a1b 100644 (file)
@@ -22,6 +22,7 @@ void ossl_cmp_mock_srv_free(OSSL_CMP_SRV_CTX *srv_ctx);
 
 int ossl_cmp_mock_srv_set1_refCert(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
 int ossl_cmp_mock_srv_set1_certOut(OSSL_CMP_SRV_CTX *srv_ctx, X509 *cert);
+int ossl_cmp_mock_srv_set1_crlOut(OSSL_CMP_SRV_CTX *srv_ctx, X509_CRL *crl);
 int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
                                     STACK_OF(X509) *chain);
 int ossl_cmp_mock_srv_set1_caPubsOut(OSSL_CMP_SRV_CTX *srv_ctx,
index b0c8dfbb8c33fdba2f441a7de6bfc891cba7e4c9..1c7bf22f6b08251f25c8244ee950388b1709744a 100644 (file)
@@ -20,6 +20,7 @@ typedef struct
 {
     X509 *refCert;             /* cert to expect for oldCertID in kur/rr msg */
     X509 *certOut;             /* certificate to be returned in cp/ip/kup msg */
+    X509_CRL *crlOut;          /* CRL to be returned in genp for crls */
     STACK_OF(X509) *chainOut;  /* chain of certOut to add to extraCerts field */
     STACK_OF(X509) *caPubsOut; /* used in caPubs of ip and in caCerts of genp */
     X509 *newWithNew;          /* to return in newWithNew of rootKeyUpdate */
@@ -87,6 +88,22 @@ static mock_srv_ctx *mock_srv_ctx_new(void)
 DEFINE_OSSL_SET1_CERT(refCert)
 DEFINE_OSSL_SET1_CERT(certOut)
 
+int ossl_cmp_mock_srv_set1_crlOut(OSSL_CMP_SRV_CTX *srv_ctx,
+                                  X509_CRL *crl)
+{
+    mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
+
+    if (ctx == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+    if (crl != NULL && !X509_CRL_up_ref(crl))
+        return 0;
+    X509_CRL_free(ctx->crlOut);
+    ctx->crlOut = crl;
+    return 1;
+}
+
 int ossl_cmp_mock_srv_set1_chainOut(OSSL_CMP_SRV_CTX *srv_ctx,
                                     STACK_OF(X509) *chain)
 {
@@ -391,6 +408,46 @@ static OSSL_CMP_PKISI *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
     return OSSL_CMP_PKISI_dup(ctx->statusOut);
 }
 
+/* return -1 for error, 0 for no update available */
+static int check_client_crl(const STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList,
+                            const X509_CRL *crl)
+{
+    OSSL_CMP_CRLSTATUS *crlstatus;
+    DIST_POINT_NAME *dpn;
+    GENERAL_NAMES *issuer;
+    ASN1_TIME *thisupd = NULL;
+
+    if (sk_OSSL_CMP_CRLSTATUS_num(crlStatusList) != 1) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CRLSTATUSLIST);
+        return -1;
+    }
+    if (crl == NULL)
+        return 0;
+
+    crlstatus = sk_OSSL_CMP_CRLSTATUS_value(crlStatusList, 0);
+    if (!OSSL_CMP_CRLSTATUS_get0(crlstatus, &dpn, &issuer, &thisupd))
+        return -1;
+
+    if (issuer != NULL) {
+        GENERAL_NAME *gn = sk_GENERAL_NAME_value(issuer, 0);
+
+        if (gn != NULL && gn->type == GEN_DIRNAME) {
+            X509_NAME *gen_name = gn->d.dirn;
+
+            if (X509_NAME_cmp(gen_name, X509_CRL_get_issuer(crl)) != 0) {
+                ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CRL_ISSUER);
+                return -1;
+            }
+        } else {  
+            ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);  
+            return -1; /* error according to RFC 9483 section 4.3.4 */  
+        }
+    }
+
+    return thisupd == NULL
+        || ASN1_TIME_compare(thisupd, X509_CRL_get0_lastUpdate(crl)) < 0;
+}
+
 static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
                                         const OSSL_CMP_ITAV *req)
 {
@@ -418,6 +475,21 @@ static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
                                                         ctx->oldWithNew);
         }
         break;
+    case NID_id_it_crlStatusList:
+        {
+            STACK_OF(OSSL_CMP_CRLSTATUS) *crlstatuslist;
+            int res = 0;
+
+            if (!OSSL_CMP_ITAV_get0_crlStatusList(req, &crlstatuslist))
+                return NULL;
+
+            res = check_client_crl(crlstatuslist, ctx->crlOut);
+            if (res < 0)
+                rsp = NULL;
+            else
+                rsp = OSSL_CMP_ITAV_new_crls(res == 0 ? NULL : ctx->crlOut);
+        }
+        break;
     default:
         rsp = OSSL_CMP_ITAV_dup(req);
     }
index daa6a4c49b64a1bcd4f89cb2960cfb668a780912..f20e5098ca9ca20a65e5c0a01cbcc07c17c61e42 100644 (file)
@@ -120,6 +120,11 @@ ASN1_ADB(OSSL_CMP_ITAV) = {
     ADB_ENTRY(NID_id_it_certProfile,
               ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.certProfile,
                                    ASN1_UTF8STRING)),
+    ADB_ENTRY(NID_id_it_crlStatusList,
+              ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.crlStatusList,
+                                   OSSL_CMP_CRLSTATUS)),
+    ADB_ENTRY(NID_id_it_crls,
+              ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.crls, X509_CRL))
 } ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0,
                &infotypeandvalue_default_tt, NULL);
 
@@ -138,6 +143,20 @@ ASN1_SEQUENCE(OSSL_CMP_ROOTCAKEYUPDATE) = {
 } ASN1_SEQUENCE_END(OSSL_CMP_ROOTCAKEYUPDATE)
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
 
+ASN1_CHOICE(OSSL_CMP_CRLSOURCE) = {
+    ASN1_EXP(OSSL_CMP_CRLSOURCE, value.dpn, DIST_POINT_NAME, 0),
+    ASN1_EXP(OSSL_CMP_CRLSOURCE, value.issuer, GENERAL_NAMES, 1),
+} ASN1_CHOICE_END(OSSL_CMP_CRLSOURCE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSOURCE)
+#define OSSL_CMP_CRLSOURCE_DPN 0
+#define OSSL_CMP_CRLSOURCE_ISSUER 1
+
+ASN1_SEQUENCE(OSSL_CMP_CRLSTATUS) = {
+    ASN1_SIMPLE(OSSL_CMP_CRLSTATUS, source, OSSL_CMP_CRLSOURCE),
+    ASN1_OPT(OSSL_CMP_CRLSTATUS, thisUpdate, ASN1_TIME)
+} ASN1_SEQUENCE_END(OSSL_CMP_CRLSTATUS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS)
+
 OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value)
 {
     OSSL_CMP_ITAV *itav;
@@ -339,6 +358,243 @@ int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav,
     return 1;
 }
 
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList)
+{
+    OSSL_CMP_ITAV *itav;
+
+    if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+        return NULL;
+    itav->infoType = OBJ_nid2obj(NID_id_it_crlStatusList);
+    itav->infoValue.crlStatusList = crlStatusList;
+    return itav;
+}
+
+int OSSL_CMP_ITAV_get0_crlStatusList(const OSSL_CMP_ITAV *itav,
+                                     STACK_OF(OSSL_CMP_CRLSTATUS) **out)
+{
+    if (itav == NULL || out == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    if (OBJ_obj2nid(itav->infoType) != NID_id_it_crlStatusList) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+    *out = itav->infoValue.crlStatusList;
+    return 1;
+}
+
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
+                                            const GENERAL_NAMES *issuer,
+                                            const ASN1_TIME *thisUpdate)
+{
+    OSSL_CMP_CRLSOURCE *crlsource;
+    OSSL_CMP_CRLSTATUS *crlstatus;
+
+    if (dpn == NULL && issuer == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+        return NULL;
+    }
+    if (dpn != NULL && issuer != NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return NULL;
+    }
+
+    if ((crlstatus = OSSL_CMP_CRLSTATUS_new()) == NULL)
+        return NULL;
+    crlsource = crlstatus->source;
+
+    if (dpn != NULL) {
+        crlsource->type = OSSL_CMP_CRLSOURCE_DPN;
+        if ((crlsource->value.dpn = DIST_POINT_NAME_dup(dpn)) == NULL)
+            goto err;
+    } else {
+        crlsource->type = OSSL_CMP_CRLSOURCE_ISSUER;
+        if ((crlsource->value.issuer =
+             sk_GENERAL_NAME_deep_copy(issuer, GENERAL_NAME_dup,
+                                       GENERAL_NAME_free)) == NULL)
+            goto err;
+    }
+
+    if (thisUpdate != NULL
+            && (crlstatus->thisUpdate = ASN1_TIME_dup(thisUpdate)) == NULL)
+        goto err;
+    return crlstatus;
+
+ err:
+    OSSL_CMP_CRLSTATUS_free(crlstatus);
+    return NULL;
+}
+
+static GENERAL_NAMES *gennames_new(const X509_NAME *nm)
+{
+    GENERAL_NAMES *names;
+    GENERAL_NAME *name = NULL;
+
+    if ((names = sk_GENERAL_NAME_new_reserve(NULL, 1)) == NULL)
+        return NULL;
+    if (!GENERAL_NAME_set1_X509_NAME(&name, nm)) {
+        sk_GENERAL_NAME_free(names);
+        return NULL;
+    }
+    (void)sk_GENERAL_NAME_push(names, name); /* cannot fail */
+    return names;
+}
+
+static int gennames_allowed(GENERAL_NAMES *names, int only_DN)
+{
+    if (names == NULL)
+        return 0;
+    if (!only_DN)
+        return 1;
+    return sk_GENERAL_NAME_num(names) == 1
+        && sk_GENERAL_NAME_value(names, 0)->type == GEN_DIRNAME;
+}
+
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
+                                              const X509 *cert, int only_DN)
+{
+    STACK_OF(DIST_POINT) *crldps = NULL;
+    ISSUING_DIST_POINT *idp = NULL;
+    DIST_POINT_NAME *dpn = NULL;
+    AUTHORITY_KEYID *akid = NULL;
+    GENERAL_NAMES *issuers = NULL;
+    const GENERAL_NAMES *CRLissuer = NULL;
+    const ASN1_TIME *last = crl == NULL ? NULL : X509_CRL_get0_lastUpdate(crl);
+    OSSL_CMP_CRLSTATUS *status = NULL;
+    int i, NID_akid = NID_authority_key_identifier;
+
+    /*
+     * Note:
+     * X509{,_CRL}_get_ext_d2i(..., NID, ..., NULL) return the 1st extension with
+     * given NID that is available, if any. If there are more, this is an error.
+     */
+    if (cert != NULL) {
+        crldps = X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL);
+        /* if available, take the first suitable element */
+        for (i = 0; i < sk_DIST_POINT_num(crldps); i++) {
+            DIST_POINT *dp = sk_DIST_POINT_value(crldps, i);
+
+            if (dp == NULL)
+                continue;
+            if ((dpn = dp->distpoint) != NULL) {
+                CRLissuer = NULL;
+                break;
+            }
+            if (gennames_allowed(dp->CRLissuer, only_DN) && CRLissuer == NULL)
+                /* don't break because any dp->distpoint in list is preferred */
+                CRLissuer = dp->CRLissuer;
+        }
+    } else {
+        if (crl == NULL) {
+            ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+            return NULL;
+        }
+        idp = X509_CRL_get_ext_d2i(crl,
+                                   NID_issuing_distribution_point, NULL, NULL);
+        if (idp != NULL && idp->distpoint != NULL)
+            dpn = idp->distpoint;
+    }
+
+    if (dpn == NULL && CRLissuer == NULL) {
+        if (cert != NULL) {
+            akid = X509_get_ext_d2i(cert, NID_akid, NULL, NULL);
+            if (akid != NULL && gennames_allowed(akid->issuer, only_DN))
+                CRLissuer = akid->issuer;
+            else
+                CRLissuer = issuers = gennames_new(X509_get_issuer_name(cert));
+        }
+        if (CRLissuer == NULL && crl != NULL) {
+            akid = X509_CRL_get_ext_d2i(crl, NID_akid, NULL, NULL);
+            if (akid != NULL && gennames_allowed(akid->issuer, only_DN))
+                CRLissuer = akid->issuer;
+            else
+                CRLissuer = issuers = gennames_new(X509_CRL_get_issuer(crl));
+        }
+        if (CRLissuer == NULL)
+            goto end;
+    }
+
+    status = OSSL_CMP_CRLSTATUS_new1(dpn, CRLissuer, last);
+ end:
+    sk_DIST_POINT_pop_free(crldps, DIST_POINT_free);
+    ISSUING_DIST_POINT_free(idp);
+    AUTHORITY_KEYID_free(akid);
+    sk_GENERAL_NAME_pop_free(issuers, GENERAL_NAME_free);
+    return status;
+}
+
+int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus,
+                            DIST_POINT_NAME **dpn, GENERAL_NAMES **issuer,
+                            ASN1_TIME **thisUpdate)
+{
+    OSSL_CMP_CRLSOURCE *crlsource;
+
+    if (crlstatus == NULL || dpn == NULL || issuer == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+    if ((crlsource = crlstatus->source) == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+
+    if (crlsource->type == OSSL_CMP_CRLSOURCE_DPN) {
+        *dpn = crlsource->value.dpn;
+        *issuer = NULL;
+    } else if (crlsource->type == OSSL_CMP_CRLSOURCE_ISSUER) {
+        *dpn = NULL;
+        *issuer = crlsource->value.issuer;
+    } else {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+    if (thisUpdate != NULL)
+        *thisUpdate = crlstatus->thisUpdate;
+    return 1;
+}
+
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crl)
+{
+    OSSL_CMP_ITAV *itav;
+    X509_CRL *crl_copy = NULL;
+    STACK_OF(X509_CRL) *crls = NULL;
+
+    if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+        return NULL;
+
+    if (crl != NULL) {
+        if ((crls = sk_X509_CRL_new_reserve(NULL, 1)) == NULL
+                || (crl_copy = X509_CRL_dup(crl)) == NULL)
+            goto err;
+        (void)sk_X509_CRL_push(crls, crl_copy); /* cannot fail */
+    }
+
+    itav->infoType = OBJ_nid2obj(NID_id_it_crls);
+    itav->infoValue.crls = crls;
+    return itav;
+
+ err:
+    sk_X509_CRL_free(crls);
+    OSSL_CMP_ITAV_free(itav);
+    return NULL;
+}
+
+int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *itav, STACK_OF(X509_CRL) **out)
+{
+    if (itav == NULL || out == NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    if (OBJ_obj2nid(itav->infoType) != NID_id_it_crls) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+    *out = itav->infoValue.crls;
+    return 1;
+}
+
 /* get ASN.1 encoded integer, return -2 on error; -1 is valid for certReqId */
 int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
 {
index 56ac3691d7677e2879d8cb1b09de612bae9213b5..689aa6a9520f71befcd1d112091c2ec63757b979 100644 (file)
@@ -85,12 +85,15 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     "failure obtaining random"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAIL_INFO_OUT_OF_RANGE),
     "fail info out of range"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GENERATE_CRLSTATUS),
+    "error creating crlstatus"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GETTING_GENP), "getting genp"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GET_ITAV), "get itav"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_GENP), "invalid genp"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ROOTCAKEYUPDATE),
-     "invalid rootcakeyupdate"},
+    "invalid rootcakeyupdate"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CERTID), "missing certid"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION),
     "missing key input for creating protection"},
@@ -146,7 +149,9 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNCLEAN_CTX), "unclean ctx"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CERTPROFILE),
-     "unexpected certprofile"},
+    "unexpected certprofile"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CRLSTATUSLIST),
+    "unexpected crlstatuslist"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
     "unexpected pkistatus"},
@@ -156,6 +161,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
     "unknown algorithm id"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CRL_ISSUER), "unknown crl issuer"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_PKISTATUS), "unknown pkistatus"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM),
     "unsupported algorithm"},
index 7c38d3367c5a73a4f76547aafab70da427dbf13c..8d92019c8392f00bbfffa1b696368baa5218a8c2 100644 (file)
@@ -346,3 +346,63 @@ int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
     X509_free(oldWithOld_copy);
     return res;
 }
+
+int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
+                            const X509_CRL *last_crl,
+                            X509_CRL **crl)
+{
+    OSSL_CMP_CRLSTATUS *status = NULL;
+    STACK_OF(OSSL_CMP_CRLSTATUS) *list = NULL;
+    OSSL_CMP_ITAV *req = NULL, *itav = NULL;
+    STACK_OF(X509_CRL) *crls;
+    int res = 0;
+
+    if (crl == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+    *crl = NULL;
+
+    if ((status = OSSL_CMP_CRLSTATUS_create(last_crl, crlcert, 1)) == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_GENERATE_CRLSTATUS);
+        goto end;
+    }
+    if ((list = sk_OSSL_CMP_CRLSTATUS_new_reserve(NULL, 1)) == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_GENERATE_CRLSTATUS);
+        goto end;
+    }
+    (void)sk_OSSL_CMP_CRLSTATUS_push(list, status); /* cannot fail */
+
+    if ((req = OSSL_CMP_ITAV_new0_crlStatusList(list)) == NULL)
+        goto end;
+    status = NULL;
+    list = NULL;
+
+    if ((itav = get_genm_itav(ctx, req, NID_id_it_crls, "crl")) == NULL)
+        goto end;
+
+    if (!OSSL_CMP_ITAV_get0_crls(itav, &crls))
+        goto end;
+
+    if (crls == NULL) { /* no CRL update available */
+        res = 1;
+        goto end;
+    }
+    if (sk_X509_CRL_num(crls) != 1) {
+        ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_GENP,
+                       "Unexpected number of CRLs in genp: %d",
+                       sk_X509_CRL_num(crls));
+        goto end;
+    }
+
+    if ((*crl = sk_X509_CRL_value(crls, 0)) == NULL || !X509_CRL_up_ref(*crl)) {
+        *crl = NULL;
+        goto end;
+    }
+    res = 1;
+ end:
+    OSSL_CMP_CRLSTATUS_free(status);
+    sk_OSSL_CMP_CRLSTATUS_free(list);
+    OSSL_CMP_ITAV_free(itav);
+    return res;
+}
index 4358b38873f357579bf6267601f07463adbf288d..59205ef8c72e42570e55bf2e8c6c1319c41c6fd1 100644 (file)
@@ -89,34 +89,6 @@ int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name)
         || (name->type == GEN_DIRNAME && IS_NULL_DN(name->d.directoryName));
 }
 
-/* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */
-static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src)
-{
-    GENERAL_NAME *name;
-
-    if (!ossl_assert(tgt != NULL))
-        return 0;
-    if ((name = GENERAL_NAME_new()) == NULL)
-        goto err;
-    name->type = GEN_DIRNAME;
-
-    if (src == NULL) { /* NULL-DN */
-        if ((name->d.directoryName = X509_NAME_new()) == NULL)
-            goto err;
-    } else if (!X509_NAME_set(&name->d.directoryName, src)) {
-        goto err;
-    }
-
-    GENERAL_NAME_free(*tgt);
-    *tgt = name;
-
-    return 1;
-
- err:
-    GENERAL_NAME_free(name);
-    return 0;
-}
-
 /*
  * Set the sender name in PKIHeader.
  * when nm is NULL, sender is set to an empty string
@@ -126,14 +98,14 @@ int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm)
 {
     if (!ossl_assert(hdr != NULL))
         return 0;
-    return set1_general_name(&hdr->sender, nm);
+    return GENERAL_NAME_set1_X509_NAME(&hdr->sender, nm);
 }
 
 int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm)
 {
     if (!ossl_assert(hdr != NULL))
         return 0;
-    return set1_general_name(&hdr->recipient, nm);
+    return GENERAL_NAME_set1_X509_NAME(&hdr->recipient, nm);
 }
 
 int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr)
index 89f05d7536690dd711e38ca0154a645569e2f9b9..9ebd1858a5574908521ed1c0466247db3827700c 100644 (file)
@@ -211,6 +211,36 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
 typedef struct ossl_cmp_rootcakeyupdate_st OSSL_CMP_ROOTCAKEYUPDATE;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
 
+typedef struct ossl_cmp_certreqtemplate_st OSSL_CMP_CERTREQTEMPLATE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTREQTEMPLATE)
+
+/*-
+ * CRLSource ::= CHOICE {
+ *      dpn          [0] DistributionPointName,
+ *      issuer       [1] GeneralNames }
+ */
+
+typedef struct ossl_cmp_crlsource_st {
+    int type;
+    union {
+        DIST_POINT_NAME *dpn;
+        GENERAL_NAMES *issuer;
+    } value;
+} OSSL_CMP_CRLSOURCE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLSOURCE)
+
+/*
+ * CRLStatus ::= SEQUENCE {
+ *      source       CRLSource,
+ *      thisUpdate   Time OPTIONAL }
+ */
+
+struct ossl_cmp_crlstatus_st {
+    OSSL_CMP_CRLSOURCE *source;
+    ASN1_TIME *thisUpdate;
+}; /* OSSL_CMP_CRLSTATUS */
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS)
+
 /*-
  * declared already here as it will be used in OSSL_CMP_MSG (nested) and
  * infoType and infoValue
@@ -264,6 +294,11 @@ struct ossl_cmp_itav_st {
         X509 *rootCaCert;
         /* NID_id_it_rootCaKeyUpdate - Root CA Certificate Update */
         OSSL_CMP_ROOTCAKEYUPDATE *rootCaKeyUpdate;
+        /* NID_id_it_crlStatusList -  CRL Update Retrieval */
+        STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList;
+        /* NID_id_it_crls - Certificate Status Lists */
+        STACK_OF(X509_CRL) *crls;
+
         /* this is to be used for so far undeclared objects */
         ASN1_TYPE *other;
     } infoValue;
index 1607ad835f3d40a834062873aba802b9e013c579..5102c481e34afdc594770cffe03731c0dd4d98ed 100644 (file)
@@ -234,7 +234,9 @@ CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain
 CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
 CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
 CMP_R_FAIL_INFO_OUT_OF_RANGE:129:fail info out of range
+CMP_R_GENERATE_CRLSTATUS:198:error creating crlstatus
 CMP_R_GETTING_GENP:192:getting genp
+CMP_R_GET_ITAV:199:get itav
 CMP_R_INVALID_ARGS:100:invalid args
 CMP_R_INVALID_GENP:193:invalid genp
 CMP_R_INVALID_OPTION:174:invalid option
@@ -276,6 +278,7 @@ CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
 CMP_R_TRANSFER_ERROR:159:transfer error
 CMP_R_UNCLEAN_CTX:191:unclean ctx
 CMP_R_UNEXPECTED_CERTPROFILE:196:unexpected certprofile
+CMP_R_UNEXPECTED_CRLSTATUSLIST:201:unexpected crlstatuslist
 CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
 CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
 CMP_R_UNEXPECTED_POLLREQ:105:unexpected pollreq
@@ -283,6 +286,7 @@ CMP_R_UNEXPECTED_PVNO:153:unexpected pvno
 CMP_R_UNEXPECTED_SENDER:106:unexpected sender
 CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
 CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
+CMP_R_UNKNOWN_CRL_ISSUER:200:unknown crl issuer
 CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus
 CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
 CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
index 8f560e171cabbd30c4c1a8aca13a3d109d7dc3ef..839b2c1afefc47acddca42fe34cc8eddd5877223 100644 (file)
@@ -327,6 +327,7 @@ ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
 
 
 IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
+IMPLEMENT_ASN1_DUP_FUNCTION(DIST_POINT_NAME)
 
 ASN1_SEQUENCE(DIST_POINT) = {
         ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
index 1f67bf2f63ab879ea24146da0d42234ff1f75066..c71e5b91116d234fedc4e21c612dfcc24fa1932c 100644 (file)
@@ -58,6 +58,35 @@ GENERAL_NAME *GENERAL_NAME_dup(const GENERAL_NAME *a)
                                     (char *)a);
 }
 
+int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src)
+{
+    GENERAL_NAME *name;
+
+    if (tgt == NULL){
+        ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+        return 0;
+    }
+
+    if ((name = GENERAL_NAME_new()) == NULL)
+        return 0;
+    name->type = GEN_DIRNAME;
+
+    if (src == NULL) { /* NULL-DN */
+        if ((name->d.directoryName = X509_NAME_new()) == NULL)
+            goto err;
+    } else if (!X509_NAME_set(&name->d.directoryName, src)) {
+        goto err;
+    }
+
+    GENERAL_NAME_free(*tgt);
+    *tgt = name;
+    return 1;
+
+ err:
+    GENERAL_NAME_free(name);
+    return 0;
+}
+
 static int edipartyname_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b)
 {
     int res;
index c7cb6d5d4fb3ed2b17debfeebfe16142a9d26cbb..aab005baaef8d91d02de3123ad5d7563912e8f91 100644 (file)
@@ -1471,6 +1471,10 @@ DEPEND[html/man3/EVP_whirlpool.html]=man3/EVP_whirlpool.pod
 GENERATE[html/man3/EVP_whirlpool.html]=man3/EVP_whirlpool.pod
 DEPEND[man/man3/EVP_whirlpool.3]=man3/EVP_whirlpool.pod
 GENERATE[man/man3/EVP_whirlpool.3]=man3/EVP_whirlpool.pod
+DEPEND[html/man3/GENERAL_NAME.html]=man3/GENERAL_NAME.pod
+GENERATE[html/man3/GENERAL_NAME.html]=man3/GENERAL_NAME.pod
+DEPEND[man/man3/GENERAL_NAME.3]=man3/GENERAL_NAME.pod
+GENERATE[man/man3/GENERAL_NAME.3]=man3/GENERAL_NAME.pod
 DEPEND[html/man3/HMAC.html]=man3/HMAC.pod
 GENERATE[html/man3/HMAC.html]=man3/HMAC.pod
 DEPEND[man/man3/HMAC.3]=man3/HMAC.pod
@@ -3327,6 +3331,7 @@ html/man3/EVP_sha3_224.html \
 html/man3/EVP_sm3.html \
 html/man3/EVP_sm4_cbc.html \
 html/man3/EVP_whirlpool.html \
+html/man3/GENERAL_NAME.html \
 html/man3/HMAC.html \
 html/man3/MD5.html \
 html/man3/MDC2_Init.html \
@@ -3979,6 +3984,7 @@ man/man3/EVP_sha3_224.3 \
 man/man3/EVP_sm3.3 \
 man/man3/EVP_sm4_cbc.3 \
 man/man3/EVP_whirlpool.3 \
+man/man3/GENERAL_NAME.3 \
 man/man3/HMAC.3 \
 man/man3/MD5.3 \
 man/man3/MDC2_Init.3 \
index f9f33db569f7341f45c708eef14d470cc618e0c7..abfac3c420bff5d89a4b9387808c686d511a56c5 100644 (file)
@@ -74,6 +74,9 @@ Server authentication options:
 [B<-newwithnew> I<filename>]
 [B<-newwithold> I<filename>]
 [B<-oldwithnew> I<filename>]
+[B<-crlcert> I<filename>]
+[B<-oldcrl> I<filename>]
+[B<-crlout> I<filename>]
 
 Client authentication and protection options:
 
@@ -91,6 +94,7 @@ Client authentication and protection options:
 Credentials format options:
 
 [B<-certform> I<PEM|DER>]
+[B<-crlform> I<PEM|DER>]
 [B<-keyform> I<PEM|DER|P12|ENGINE>]
 [B<-otherpass> I<arg>]
 {- $OpenSSL::safe::opt_engine_synopsis -}{- $OpenSSL::safe::opt_provider_synopsis -}
@@ -134,6 +138,7 @@ Mock server options:
 [B<-srv_untrusted> I<filenames>|I<uris>]
 [B<-ref_cert> I<filename>|I<uri>]
 [B<-rsp_cert> I<filename>|I<uri>]
+[B<-rsp_crl> I<filename>|I<uri>]
 [B<-rsp_extracerts> I<filenames>|I<uris>]
 [B<-rsp_capubs> I<filenames>|I<uris>]
 [B<-rsp_newwithnew> I<filename>|I<uri>]
@@ -247,7 +252,8 @@ ITAV B<infoType>s is printed to stdout.
 
 Set InfoType name to use for requesting specific info in B<genm>,
 e.g., C<signKeyPairTypes>.
-So far, there is specific support for C<caCerts> and C<rootCaCert>.
+So far, there is specific support for C<caCerts>, C<rootCaCert>
+and C<crlStatusList>.
 
 =item B<-profile> I<name>
 
@@ -733,6 +739,24 @@ The file to save any oldWithNew certificate
 received in a genp message of infoType C<rootCaKeyUpdate>.
 If on success no such cert was received, this is indicated by deleting the file.
 
+=item B<-crlcert> I<filename>
+
+Certificate used for specifying a CRL issuer when requesting a CRL 
+in a genm message with infoType C<crlStatusList>.
+Any available distribution point name is preferred over issuer names.
+
+=item B<-oldcrl> I<filename>
+
+CRL used for specifying a CRL issuer when requesting a CRL 
+in a genm message with infoType C<crlStatusList>.
+Any available distribution point name is preferred over issuer names.
+If also B<-crlcrt> is given, its data is preferred over data from B<-oldcrl>.
+
+=item B<-crlout> I<filename>
+
+The file to save CRL received in a genp message of infoType C<crls>.
+If on success no such CRL was received, this is indicated by deleting the file.
+
 =back
 
 =head2 Client authentication options
@@ -858,6 +882,11 @@ Send request messages without CMP-level protection.
 File format to use when saving a certificate to a file.
 Default value is PEM.
 
+=item B<-crlform> I<PEM|DER>
+
+File format to use when saving a CRL to a file.
+Default value is DER.
+
 =item B<-keyform> I<PEM|DER|P12|ENGINE>
 
 The format of the key input; unspecified by default.
@@ -866,7 +895,7 @@ See L<openssl(1)/Format Options> for details.
 =item B<-otherpass> I<arg>
 
 Pass phrase source for certificate given with the B<-trusted>, B<-untrusted>,
-B<-own_trusted>, B<-srvcert>, B<-out_trusted>, B<-extracerts>,
+B<-own_trusted>, B<-srvcert>, B<-crlcert>, B<-out_trusted>, B<-extracerts>,
 B<-srv_trusted>, B<-srv_untrusted>, B<-ref_cert>, B<-rsp_cert>,
 B<-rsp_extracerts>, B<-rsp_capubs>,
 B<-rsp_newwithnew>, B<-rsp_newwithold>, B<-rsp_oldwithnew>,
@@ -1141,6 +1170,10 @@ Certificate to be expected for RR messages and any oldCertID in KUR messages.
 
 Certificate to be returned as mock enrollment result.
 
+=item B<-rsp_crl> I<filename>|I<uri>
+
+CRL to be returned in genp of type C<crls>.
+
 =item B<-rsp_extracerts> I<filenames>|I<uris>
 
 Extra certificates to be included in mock certification responses.
@@ -1438,7 +1471,8 @@ The B<cmp> application was added in OpenSSL 3.0.
 
 The B<-engine> option was deprecated in OpenSSL 3.0.
 
-The B<-profile> option was added in OpenSSL 3.3.
+B<-profile>, B<-crlcert>, B<-oldcrl>, B<-crlout>, B<-crlform>
+and B<-rsp_crl> options were added in OpenSSL 3.3.
 
 =head1 COPYRIGHT
 
diff --git a/doc/man3/GENERAL_NAME.pod b/doc/man3/GENERAL_NAME.pod
new file mode 100644 (file)
index 0000000..903a339
--- /dev/null
@@ -0,0 +1,41 @@
+=pod
+
+=head1 NAME
+
+GENERAL_NAME,
+GENERAL_NAME_set1_X509_NAME
+- GENERAL_NAME method routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509v3.h>
+
+ typedef struct GENERAL_NAME_st GENERAL_NAME;
+
+ int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src);
+
+=head1 DESCRIPTION
+
+GENERAL_NAME_set1_X509_NAME() creates a new GENERAL_NAME of type GEN_DIRNAME
+and populates it based on provided X509_NAME I<src> which can be NULL.
+I<tgt> must not be NULL. If successful, I<*tgt> will be set to point
+to the newly created GENERAL_NAME.
+
+=head1 RETURN VALUES
+
+GENERAL_NAME_set1_X509_NAME() return 1 on success, 0 on error.
+
+=head1 HISTORY
+
+GENERAL_NAME_set1_X509_NAME() was added in OpenSSL 3.3.
+
+=head1 COPYRIGHT
+
+Copyright 2007-2024 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<https://www.openssl.org/source/license.html>.
+
+=cut
index 133907d8acdcb1fb1c563ca317acaf990eb47a8f..982f840a8ec96a5db2fd330f499a4188ae5c2b7a 100644 (file)
@@ -7,7 +7,14 @@ OSSL_CMP_ITAV_get0_caCerts,
 OSSL_CMP_ITAV_new_rootCaCert,
 OSSL_CMP_ITAV_get0_rootCaCert,
 OSSL_CMP_ITAV_new_rootCaKeyUpdate,
-OSSL_CMP_ITAV_get0_rootCaKeyUpdate
+OSSL_CMP_ITAV_get0_rootCaKeyUpdate,
+OSSL_CMP_CRLSTATUS_new1,
+OSSL_CMP_CRLSTATUS_create,
+OSSL_CMP_CRLSTATUS_get0,
+OSSL_CMP_ITAV_new0_crlStatusList,
+OSSL_CMP_ITAV_get0_crlStatusList,
+OSSL_CMP_ITAV_new_crls,
+OSSL_CMP_ITAV_get0_crls
 - CMP utility functions for handling specific genm and genp messages
 
 =head1 SYNOPSIS
@@ -27,6 +34,21 @@ OSSL_CMP_ITAV_get0_rootCaKeyUpdate
                                         X509 **newWithOld,
                                         X509 **oldWithNew);
 
+ OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
+                                             const GENERAL_NAMES *issuer,
+                                             const ASN1_TIME *thisUpdate);
+ OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
+                                               const X509 *cert, int only_DN);
+ int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus,
+                             DIST_POINT_NAME **dpn, GENERAL_NAMES **issuer,
+                             ASN1_TIME **thisUpdate);
+ OSSL_CMP_ITAV
+ *OSSL_CMP_ITAV_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList);
+ int OSSL_CMP_ITAV_get0_crlStatusList(const OSSL_CMP_ITAV *itav,
+                                      STACK_OF(OSSL_CMP_CRLSTATUS) **out);
+ OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crl);
+ int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *itav, STACK_OF(X509_CRL) **out);
+
 =head1 DESCRIPTION
 
 ITAV is short for InfoTypeAndValue.
@@ -64,18 +86,77 @@ to the certificate contained in the oldWithNew infoValue sub-field of I<itav>.
 Each of these pointers will be set to NULL if no root CA certificate update 
 is present or the respective sub-field is not included.
 
+OSSL_CMP_CRLSTATUS_new1() allocates a new B<OSSL_CMP_CRLSTATUS> structure
+that contains either a copy of the distribution point name I<dpn>
+or a copy of the certificate issuer I<issuer>, while giving both is an error.
+If given, a copy of the CRL issuance time I<thisUpdate> is also included.
+
+OSSL_CMP_CRLSTATUS_create() is a high-level variant of OSSL_CMP_CRLSTATUS_new1().
+It fills the thisUpdate field with a copy of the thisUpdate field of I<crl> if present.
+It fills the CRLSource field with a copy of the first data item found using the I<crl>
+and/or I<cert> parameters as follows.
+Any available distribution point name is preferred over issuer names.
+Data from I<cert>, if present, is preferred over data from I<crl>.
+If no distribution point names are available,
+candidate issuer names are taken from following sources, as far as present:
+
+=over 4
+
+=item the list of distribution points in the first cRLDistributionPoints
+extension of I<cert>,
+
+=item the issuer field of the authority key identifier of I<cert>,
+
+=item the issuer DN of I<cert>,
+
+=item the issuer field of the authority key identifier of I<crl>, and
+
+=item the issuer DN of I<crl>.
+
+=back
+
+If <only_DN> is set, a candidate issuer name of type B<GENERAL_NAMES> is
+accepted only if it contains exactly one general name of type directoryName.
+
+OSSL_CMP_CRLSTATUS_get0() reads the fields of I<crlstatus>
+and assigns them to I<*dpn>, I<*issuer>, and I<*thisUpdate>.
+I<*thisUpdate> is assigned only if the I<thisUpdate> argument is not NULL.
+Depending on the choice present, either I<*dpn> or I<*issuer> will be NULL.
+I<*thisUpdate> can also be NULL if the field is not present.
+
+OSSL_CMP_ITAV_new0_crlStatusList() creates a new B<OSSL_CMP_ITAV> structure of
+type B<crlStatusList> that includes the optionally given list of
+CRL status data, each of which is of type B<OSSL_CMP_CRLSTATUS>.
+
+OSSL_CMP_ITAV_get0_crlStatusList() on success assigns to I<*out> an internal
+pointer to the list of CRL status data in the infoValue field of I<itav>.
+The pointer may be NULL if no CRL status data is included.
+It is an error if the infoType of I<itav> is not B<crlStatusList>.
+
+OSSL_CMP_ITAV_new_crls() creates a new B<OSSL_CMP_ITAV> structure
+of type B<crls> including an empty list of CRLs if the I<crl> argument is NULL
+or including a singleton list a with copy of the provided CRL otherwise.
+
+OSSL_CMP_ITAV_get0_crls() on success assigns to I<*out> an internal pointer to
+the list of CRLs contained in the infoValue field of I<itav>.
+The pointer may be NULL if no CRL is included.
+It is an error if the infoType of I<itav> is not B<crls>.
+
 =head1 NOTES
 
 CMP is defined in RFC 4210.
 
 =head1 RETURN VALUES
 
-OSSL_CMP_ITAV_new_caCerts(),
-OSSL_CMP_ITAV_new_rootCaCert(), and OSSL_CMP_ITAV_new_rootCaKeyUpdate()
+OSSL_CMP_ITAV_new_caCerts(), OSSL_CMP_ITAV_new_rootCaCert(),
+OSSL_CMP_ITAV_new_rootCaKeyUpdate(), OSSL_CMP_CRLSTATUS_new1(),
+OSSL_CMP_CRLSTATUS_create(), OSSL_CMP_ITAV_new0_crlStatusList()
+and OSSL_CMP_ITAV_new_crls()
 return a pointer to the new ITAV structure on success, or NULL on error.
 
-OSSL_CMP_ITAV_get0_caCerts(),
-OSSL_CMP_ITAV_get0_rootCaCert(), and OSSL_CMP_ITAV_get0_rootCaKeyUpdate()
+OSSL_CMP_ITAV_get0_caCerts(), OSSL_CMP_ITAV_get0_rootCaCert(),
+OSSL_CMP_ITAV_get0_rootCaKeyUpdate(), OSSL_CMP_CRLSTATUS_get0(),
+OSSL_CMP_ITAV_get0_crlStatusList() and OSSL_CMP_ITAV_get0_crls()
 return 1 on success, 0 on error.
 
 =head1 SEE ALSO
@@ -89,6 +170,11 @@ OSSL_CMP_ITAV_new_rootCaCert(), OSSL_CMP_ITAV_get0_rootCaCert(),
 OSSL_CMP_ITAV_new_rootCaKeyUpdate(), and OSSL_CMP_ITAV_get0_rootCaKeyUpdate()
 were added in OpenSSL 3.2.
 
+OSSL_CMP_CRLSTATUS_new1(), OSSL_CMP_CRLSTATUS_create(),
+OSSL_CMP_CRLSTATUS_get0(), OSSL_CMP_ITAV_new0_crlStatusList(),
+OSSL_CMP_ITAV_get0_crlStatusList(), OSSL_CMP_ITAV_new_crls()
+and OSSL_CMP_ITAV_get0_crls() were added in OpenSSL 3.3.
+
 =head1 COPYRIGHT
 
 Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
index 54632ce93697bc49f43f7989eaa1cc8fa380d2d9..56e6bb8ef2cc40ae50dcec8f47a4eeb3719a0357 100644 (file)
@@ -15,7 +15,8 @@ OSSL_CMP_try_certreq,
 OSSL_CMP_exec_RR_ses,
 OSSL_CMP_exec_GENM_ses,
 OSSL_CMP_get1_caCerts,
-OSSL_CMP_get1_rootCaKeyUpdate
+OSSL_CMP_get1_rootCaKeyUpdate,
+OSSL_CMP_get1_crlUpdate
 - functions implementing CMP client transactions
 
 =head1 SYNOPSIS
@@ -41,6 +42,9 @@ OSSL_CMP_get1_rootCaKeyUpdate
  int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
                                    const X509 *oldWithOld, X509 **newWithNew,
                                    X509 **newWithOld, X509 **oldWithNew);
+ int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
+                             const X509_CRL *last_crl,
+                             X509_CRL **crl);
 
 =head1 DESCRIPTION
 
@@ -157,6 +161,14 @@ The trust placed in it cannot be stronger than the trust placed in
 the I<oldwithold> certificate if present, otherwise it cannot be stronger than
 the weakest trust in any of the certificates in the trust store of I<ctx>.
 
+OSSL_CMP_get1_crlUpdate() uses a genm request message with infoType crlStatusList
+to obtain CRL from the CMP server referenced by I<ctx> in a genp response message
+with infoType crls. It uses I<last_crl> and I<crlcert> to create  
+a request with a status field as described for L<OSSL_CMP_CRLSTATUS_create(3)>. 
+On success it assigns to I<*crl> the CRL received.
+NULL means that no CRL was provided by the server.
+The CRL obtained this way must be freed by the caller.
+
 =head1 NOTES
 
 CMP is defined in RFC 4210 (and CRMF in RFC 4211).
@@ -193,7 +205,7 @@ and the output parameter I<checkAfter> has been used to
 assign the received value unless I<checkAfter> is NULL.
 
 OSSL_CMP_exec_RR_ses(), OSSL_CMP_get1_caCerts(),
-and OSSL_CMP_get1_rootCaKeyUpdate()
+OSSL_CMP_get1_rootCaKeyUpdate() and OSSL_CMP_get1_crlUpdate()
 return 1 on success, 0 on error.
 
 OSSL_CMP_exec_GENM_ses() returns NULL on error,
@@ -211,7 +223,7 @@ L<OSSL_CMP_CTX_new(3)>, L<OSSL_CMP_CTX_free(3)>,
 L<OSSL_CMP_CTX_set1_subjectName(3)>, L<OSSL_CMP_CTX_set0_newPkey(3)>,
 L<OSSL_CMP_CTX_set1_p10CSR(3)>, L<OSSL_CMP_CTX_set1_oldCert(3)>,
 L<OSSL_CMP_CTX_get0_newCert(3)>, L<OSSL_CMP_CTX_push0_genm_ITAV(3)>,
-L<OSSL_CMP_MSG_http_perform(3)>
+L<OSSL_CMP_MSG_http_perform(3)>, L<OSSL_CMP_CRLSTATUS_create(3)>
 
 =head1 HISTORY
 
@@ -220,8 +232,8 @@ The OpenSSL CMP support was added in OpenSSL 3.0.
 OSSL_CMP_get1_caCerts() and OSSL_CMP_get1_rootCaKeyUpdate()
 were added in OpenSSL 3.2.
 
-Support for delayed delivery of all types of response messages
-was added in OpenSSL 3.3.
+OSSL_CMP_get1_crlUpdate() and support for delayed delivery 
+of all types of response messages was added in OpenSSL 3.3.
 
 =head1 COPYRIGHT
 
index 4ecd5c0830c9f4cf530ce70c71a263b50d2c0a11..17100a45ffb5edc5707158d440b4def8a6ccbe53 100644 (file)
@@ -44,6 +44,7 @@ DISPLAYTEXT_free,
 DISPLAYTEXT_new,
 DIST_POINT_NAME_free,
 DIST_POINT_NAME_new,
+DIST_POINT_NAME_dup,
 DIST_POINT_free,
 DIST_POINT_new,
 DSAparams_dup,
@@ -135,6 +136,7 @@ OCSP_SIGNATURE_free,
 OCSP_SIGNATURE_new,
 OCSP_SINGLERESP_free,
 OCSP_SINGLERESP_new,
+OSSL_CMP_CRLSTATUS_free,
 OSSL_CMP_ITAV_dup,
 OSSL_CMP_ITAV_free,
 OSSL_CMP_MSG_dup,
index ad9eb3429d6786919b76e296331bd13120cd667b..c46b9ab594fa7f9fdacfbe20a9f455b4de9ba552 100644 (file)
@@ -228,6 +228,12 @@ DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
 {-
     generate_stack_macros("OSSL_CMP_ITAV");
 -}
+
+typedef struct ossl_cmp_crlstatus_st OSSL_CMP_CRLSTATUS;
+{-
+    generate_stack_macros("OSSL_CMP_CRLSTATUS");
+-}
+
 typedef struct ossl_cmp_revrepcontent_st OSSL_CMP_REVREPCONTENT;
 typedef struct ossl_cmp_pkisi_st OSSL_CMP_PKISI;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
@@ -257,7 +263,7 @@ void OSSL_CMP_ITAV_set0(OSSL_CMP_ITAV *itav, ASN1_OBJECT *type,
                         ASN1_TYPE *value);
 ASN1_OBJECT *OSSL_CMP_ITAV_get0_type(const OSSL_CMP_ITAV *itav);
 ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav);
-int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
+int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **sk_p,
                                    OSSL_CMP_ITAV *itav);
 void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav);
 
@@ -278,6 +284,22 @@ int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav,
                                        X509 **newWithOld,
                                        X509 **oldWithNew);
 
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
+                                              const X509 *cert, int only_DN);
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
+                                            const GENERAL_NAMES *issuer,
+                                            const ASN1_TIME *thisUpdate);
+int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus,
+                            DIST_POINT_NAME **dpn, GENERAL_NAMES **issuer,
+                            ASN1_TIME **thisUpdate);
+void OSSL_CMP_CRLSTATUS_free(OSSL_CMP_CRLSTATUS *crlstatus);
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList);
+int OSSL_CMP_ITAV_get0_crlStatusList(const OSSL_CMP_ITAV *itav,
+                                     STACK_OF(OSSL_CMP_CRLSTATUS) **out);
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crls);
+int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *it, STACK_OF(X509_CRL) **out);
+
 void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
 
 /* from cmp_ctx.c */
@@ -521,6 +543,9 @@ int OSSL_CMP_get1_caCerts(OSSL_CMP_CTX *ctx, STACK_OF(X509) **out);
 int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
                                   const X509 *oldWithOld, X509 **newWithNew,
                                   X509 **newWithOld, X509 **oldWithNew);
+int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
+                            const X509_CRL *last_crl,
+                            X509_CRL **crl);
 
 #  ifdef  __cplusplus
 }
index 0d876e501c5c2724b9dcbab197b9184ef483bec9..700ffbeb7beb622156b068845d4ba473a80c5016 100644 (file)
@@ -60,7 +60,9 @@
 #  define CMP_R_FAILED_EXTRACTING_PUBKEY                   141
 #  define CMP_R_FAILURE_OBTAINING_RANDOM                   110
 #  define CMP_R_FAIL_INFO_OUT_OF_RANGE                     129
+#  define CMP_R_GENERATE_CRLSTATUS                         198
 #  define CMP_R_GETTING_GENP                               192
+#  define CMP_R_GET_ITAV                                   199
 #  define CMP_R_INVALID_ARGS                               100
 #  define CMP_R_INVALID_GENP                               193
 #  define CMP_R_INVALID_OPTION                             174
 #  define CMP_R_TRANSFER_ERROR                             159
 #  define CMP_R_UNCLEAN_CTX                                191
 #  define CMP_R_UNEXPECTED_CERTPROFILE                     196
+#  define CMP_R_UNEXPECTED_CRLSTATUSLIST                   201
 #  define CMP_R_UNEXPECTED_PKIBODY                         133
 #  define CMP_R_UNEXPECTED_PKISTATUS                       185
 #  define CMP_R_UNEXPECTED_POLLREQ                         105
 #  define CMP_R_UNEXPECTED_SENDER                          106
 #  define CMP_R_UNKNOWN_ALGORITHM_ID                       134
 #  define CMP_R_UNKNOWN_CERT_TYPE                          135
+#  define CMP_R_UNKNOWN_CRL_ISSUER                         200
 #  define CMP_R_UNKNOWN_PKISTATUS                          186
 #  define CMP_R_UNSUPPORTED_ALGORITHM                      136
 #  define CMP_R_UNSUPPORTED_KEY_TYPE                       137
index b8711d5304f4aa7130f78cc107443e84958f963b..a967064f4c4b5a7dfed42a67eb9e2831cfbc0682 100644 (file)
@@ -178,6 +178,8 @@ typedef struct ACCESS_DESCRIPTION_st {
     GENERAL_NAME *location;
 } ACCESS_DESCRIPTION;
 
+int GENERAL_NAME_set1_X509_NAME(GENERAL_NAME **tgt, const X509_NAME *src);
+
 {-
     generate_stack_macros("ACCESS_DESCRIPTION")
     .generate_stack_macros("GENERAL_NAME");
@@ -201,6 +203,7 @@ typedef struct DIST_POINT_NAME_st {
 /* If relativename then this contains the full distribution point name */
     X509_NAME *dpname;
 } DIST_POINT_NAME;
+DECLARE_ASN1_DUP_FUNCTION(DIST_POINT_NAME)
 /* All existing reasons */
 # define CRLDP_ALL_REASONS       0x807f
 
diff --git a/test/recipes/80-test_cmp_http_data/Mock/newcrl.pem b/test/recipes/80-test_cmp_http_data/Mock/newcrl.pem
new file mode 100644 (file)
index 0000000..101d7cd
--- /dev/null
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBtDCBnQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJBVTETMBEGA1UE
+CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
+MRMwEQYDVQQDEwpzdWJpbnRlckNBFw0yNDAyMjMxNTQ3NTFaFw0zNzA5MTIxNTQ3
+NTFaoA8wDTALBgNVHRQEBAICEAcwDQYJKoZIhvcNAQELBQADggEBAFyUvxWlxjLA
+DjTq/N26EXH6GZxmDyr5tjPk1KQBRY/jPNWvxloXFIH7PAtzInJmEoF2PCDw290Z
+BRuftPaxVW1tcHAsZzL5QFSGa2wWSLGCHpZCg9twcLQbGrOq7+S2M2ZjOVxSMN1u
+ok/QLhuqniPieOUetzafqUNknYJahILnomLhPoQBzko9EdtBJkygOGdj/3T07iLy
+hicW0QlBA5B9oCIUmknnx4kCh6VlsSq9FJTs2HXZhJHF0VVFbAlbjHMFkwjTh31r
+Bc8u1D35T0kqwbTbVmtPghdpW2uJ+9LsWXdrlTGGlRJXA+3d13hKlFMFcQEavf4h
+wVlABZ6eEPo=
+-----END X509 CRL-----
diff --git a/test/recipes/80-test_cmp_http_data/Mock/oldcrl.pem b/test/recipes/80-test_cmp_http_data/Mock/oldcrl.pem
new file mode 100644 (file)
index 0000000..f596289
--- /dev/null
@@ -0,0 +1,12 @@
+-----BEGIN X509 CRL-----
+MIIBtDCBnQIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJBVTETMBEGA1UE
+CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
+MRMwEQYDVQQDEwpzdWJpbnRlckNBFw0yNDAyMjMxNTQ3MzhaFw0zNDEyMTcxNTQ3
+MzhaoA8wDTALBgNVHRQEBAICEAYwDQYJKoZIhvcNAQELBQADggEBANfH339j7LXB
+9X+Vpk1xjTSRwoIQ7C/LZbOJ4tiVaNsBd+3rlOgJEnYPuB883ylAy3TOPn9taMXe
+kmPebHC4WDhESNbwm8kdFNz6Ghvvn4TuDcSgWV8xxtw5AHVfnCs8801KI8pcn7K6
+MwGdJ7CPvB38SFn5ssKQueLySRfL+bRWXpgB79hjFE7J1ukaUr2xg3q4YFQwexld
+xuaIR0AiFyTVKWTWLEdAKRzPiYTmx1ZMyYEdwh17l6nWh/UgfUEqmK9ub2Mqh20h
+g7/Nwf0iaQS7bui7DgzkW76dbXcmAmTkU8VLznOLIheus8uj6Kl2TewO5PvjVGeu
+Fgt7CED5epw=
+-----END X509 CRL-----
index 5e330789c946ffe5e3ea332daf56400f2d85b0a6..86a11f6a368297495c29df28fa97f4d00c24a238 100644 (file)
@@ -12,6 +12,7 @@ no_cache_extracerts = 1
 
 ref_cert = signer_only.crt
 rsp_cert = signer_only.crt
+rsp_crl = newcrl.pem
 rsp_capubs = trusted.crt
 rsp_extracerts = signer_issuing.crt
 
index aabf2dc1e62ca42c86b3ebbfd3735ce218b335f3..69dff91b7d80916959521757a6ed874d1b111ffe 100644 (file)
@@ -86,6 +86,16 @@ expected,description, -section,val, -cmd,val,val2, -cacertsout,val,val2, -infoty
 0,genm rootCaCert newwithold missig arg  , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew.pem, -oldwithnew, _RESULT_DIR/test.oldwithnew.pem, -newwithold,,
 1,genm rootCaCert newwithnew newwithold  , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew3.pem, -newwithold, _RESULT_DIR/test.newwithold2.pem
 ,,,,,,,,,,,,,,,,,,,,,,
+1,genm crlStatusList with crlcert        , -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, signer_only.crt,,,,, -crlout, _RESULT_DIR/test.crlout1.pem
+1,genm crlStatusList with old crl        , -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -oldcrl, oldcrl.pem,,,,, -crlout, _RESULT_DIR/test.crlout2.pem
+1,genm crlStatusList with crlcert and old crl , -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, signer_only.crt, -oldcrl, oldcrl.pem,,, -crlout, _RESULT_DIR/test.crlout3.pem
+1,genm crlStatusList with latest crl     , -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -oldcrl, _RESULT_DIR/test.crlout3.pem,,,,, -crlout, _RESULT_DIR/test.crlout4.pem
+0,genm crlStatusList with -oldcrl referring to nonexisting file due to empty CRL response message in previous test case, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -oldcrl, _RESULT_DIR/test.crlout4.pem,,,,, -crlout, _RESULT_DIR/test.crlout5.pem
+0,genm crlStatusList with -crlcert nonexistent, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, idontexist,,,,, -crlout, _RESULT_DIR/test.crlout.pem
+0,genm crlStatusList with wrong issuer, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, server.crt,,,,, -crlout, _RESULT_DIR/test.crlout.pem
+0,genm crlStatusList missing -crlcert & -oldcrl, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,,,,,,,, -crlout, _RESULT_DIR/test.crlout.pem
+0,genm crlStatusList with wrong cert and correct crl, -section,, -cmd,genm,, BLANK,,, -infotype,crlStatusList,, -crlcert, server.crt, -oldcrl, oldcrl.pem,,, -crlout, _RESULT_DIR/test.crlout.pem
+,,,,,,,,,,,,,,,,,,,,,,
 1,profile, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile1,BLANK,,BLANK,
 0,profile wrong value, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile2,BLANK,,BLANK,
 0,profile missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,,,,,
index 77b66ee2725c9982b6ef1b1bc00f72de01a882bc..facac4db4fcaacf4672cb73c2d97a919d322f91f 100644 (file)
@@ -5536,12 +5536,23 @@ X509_STORE_CTX_set_get_crl              5663    3_2_0   EXIST::FUNCTION:
 X509_STORE_CTX_set_current_reasons      5664   3_2_0   EXIST::FUNCTION:
 OSSL_STORE_delete                       5665   3_2_0   EXIST::FUNCTION:
 BIO_ADDR_copy                           5666   3_2_0   EXIST::FUNCTION:SOCK
+DIST_POINT_NAME_dup                     ?      3_3_0   EXIST::FUNCTION:
+GENERAL_NAME_set1_X509_NAME             ?      3_3_0   EXIST::FUNCTION:
 OSSL_CMP_CTX_get0_geninfo_ITAVs         5667   3_3_0   EXIST::FUNCTION:CMP
 OSSL_CMP_HDR_get0_geninfo_ITAVs         5668   3_3_0   EXIST::FUNCTION:CMP
 OSSL_CMP_ITAV_new0_certProfile          5669   3_3_0   EXIST::FUNCTION:CMP
 OSSL_CMP_ITAV_get0_certProfile          5670   3_3_0   EXIST::FUNCTION:CMP
 OSSL_CMP_MSG_get0_certreq_publickey     5671   3_3_0   EXIST::FUNCTION:CMP
 OSSL_CMP_SRV_CTX_init_trans             5672   3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_CRLSTATUS_create               ?      3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_CRLSTATUS_free                 ?      3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_CRLSTATUS_get0                 ?      3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_CRLSTATUS_new1                 ?      3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_get0_crlStatusList        ?      3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_get0_crls                 ?      3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_new0_crlStatusList        ?      3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_new_crls                  ?      3_3_0   EXIST::FUNCTION:CMP
+OSSL_CMP_get1_crlUpdate                 ?      3_3_0   EXIST::FUNCTION:CMP
 EVP_DigestSqueeze                       5673   3_3_0   EXIST::FUNCTION:
 ERR_pop                                 5674   3_3_0   EXIST::FUNCTION:
 X509_STORE_get1_objects                 5675   3_3_0   EXIST::FUNCTION:
index bf6ae33d5acb94181a67c594da8fe6f31b1f1e31..df47478f5207c06facb5c999d6347cf3c25ad8f2 100644 (file)
@@ -53,6 +53,7 @@ EVP_RAND                                datatype
 EVP_RAND_CTX                            datatype
 EVP_SIGNATURE                           datatype
 GEN_SESSION_CB                          datatype
+GENERAL_NAME                            datatype
 NAMING_AUTHORITY                        datatype
 OPENSSL_Applink                         external
 OSSL_ALGORITHM                          datatype