]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
CMP: add support for requesting cert template using genm/genp
authorRajeev Ranjan <ranjan.rajeev@siemens.com>
Wed, 15 May 2024 11:11:09 +0000 (13:11 +0200)
committerDr. David von Oheimb <dev@ddvo.net>
Thu, 20 Jun 2024 11:38:13 +0000 (13:38 +0200)
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/24409)

24 files changed:
apps/cmp.c
apps/lib/cmp_mock_srv.c
crypto/cmp/cmp_asn.c
crypto/cmp/cmp_err.c
crypto/cmp/cmp_genm.c
crypto/cmp/cmp_local.h
crypto/crmf/crmf_asn.c
crypto/crmf/crmf_local.h
crypto/err/openssl.txt
doc/build.info
doc/man1/openssl-cmp.pod.in
doc/man3/OSSL_CMP_ATAV_set0.pod [new file with mode: 0644]
doc/man3/OSSL_CMP_ITAV_new_caCerts.pod
doc/man3/OSSL_CMP_exec_certreq.pod
doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod
doc/man3/X509_dup.pod
doc/man3/d2i_X509.pod
include/internal/crmf.h [new file with mode: 0644]
include/openssl/cmp.h.in
include/openssl/cmperr.h
include/openssl/crmf.h.in
test/recipes/80-test_cmp_http_data/test_commands.csv
util/libcrypto.num
util/other.syms

index 8d880c50c8eebea44e0f2003e2510f3518647624..dc2a1c3a6aee09fe06b318d2e77240c352edcde0 100644 (file)
@@ -97,6 +97,8 @@ static char *opt_oldwithnew = NULL;
 static char *opt_crlcert = NULL;
 static char *opt_oldcrl = NULL;
 static char *opt_crlout = NULL;
+static char *opt_template = NULL;
+static char *opt_keyspec = NULL;
 
 /* client authentication */
 static char *opt_ref = NULL;
@@ -225,6 +227,7 @@ typedef enum OPTION_choice {
     OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY,
 
     OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO,
+    OPT_TEMPLATE, OPT_KEYSPEC,
 
     OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT,
     OPT_DAYS, OPT_REQEXTS,
@@ -313,6 +316,10 @@ const OPTIONS cmp_options[] = {
      "Comma-separated list of OID and value to place in generalInfo PKIHeader"},
     {OPT_MORE_STR, 0, 0,
      "of form <OID>:int:<n> or <OID>:str:<s>, e.g. \'1.2.3.4:int:56789, id-kp:str:name'"},
+    { "template", OPT_TEMPLATE, 's',
+      "File to save certTemplate received in genp of type certReqTemplate"},
+    { "keyspec", OPT_KEYSPEC, 's',
+      "Optional file to save Key specification received in genp of type certReqTemplate"},
 
     OPT_SECTION("Certificate enrollment"),
     {"newkey", OPT_NEWKEY, 's',
@@ -620,6 +627,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {&opt_config}, {&opt_section}, {(char **)&opt_verbosity},
 
     {&opt_cmd_s}, {&opt_infotype_s}, {&opt_profile}, {&opt_geninfo},
+    {&opt_template}, {&opt_keyspec},
 
     {&opt_newkey}, {&opt_newkeypass}, {&opt_subject},
     {(char **)&opt_days}, {&opt_reqexts},
@@ -2176,6 +2184,17 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
         if (opt_oldwithnew != NULL)
             CMP_warn1("-oldwithnew %s", msg);
     }
+    if (opt_cmd != CMP_GENM || opt_infotype != NID_id_it_certReqTemplate) {
+        const char *msg = "option is ignored unless -cmd 'genm' and -infotype 'certReqTemplate' is given";
+
+        if (opt_template != NULL)
+            CMP_warn1("-template %s", msg);
+        if (opt_keyspec != NULL)
+            CMP_warn1("-keyspec %s", msg);
+    } else {
+        if (opt_template == NULL)
+            CMP_err("missing -template option for genm with infotype certReqTemplate");
+    }
 
     if (!setup_verification_ctx(ctx))
         goto err;
@@ -2420,6 +2439,57 @@ static int save_crl_or_delete(X509_CRL *crl, const char *file, const char *desc)
     return (crl == NULL) ? delete_file(file, desc) : save_crl(crl, file, desc);
 }
 
+static int save_template(const char *file, const OSSL_CRMF_CERTTEMPLATE *tmpl)
+{
+    BIO *bio = BIO_new_file(file, "wb");
+
+    if (bio == NULL) {
+        CMP_err1("error saving certTemplate from genp: cannot open file %s",
+                 file);
+        return 0;
+    }
+    if (!ASN1_i2d_bio_of(OSSL_CRMF_CERTTEMPLATE, i2d_OSSL_CRMF_CERTTEMPLATE,
+                         bio, tmpl)) {
+        CMP_err1("error saving certTemplate from genp: cannot write file %s",
+                 file);
+        return 0;
+    } else {
+        CMP_info1("stored certTemplate from genp to file '%s'", file);
+    }
+    BIO_free(bio);
+    return 1;
+}
+
+static int save_keyspec(const char *file, const OSSL_CMP_ATAVS *keyspec)
+{
+    BIO *bio = BIO_new_file(file, "wb");
+
+    if (bio == NULL) {
+        CMP_err1("error saving keySpec from genp: cannot open file %s", file);
+        return 0;
+    }
+
+    if (!ASN1_i2d_bio_of(OSSL_CMP_ATAVS, i2d_OSSL_CMP_ATAVS, bio, keyspec)) {
+        CMP_err1("error saving keySpec from genp: cannot write file %s", file);
+        return 0;
+    } else {
+        CMP_info1("stored keySpec from genp to file '%s'", file);
+    }
+    BIO_free(bio);
+    return 1;
+}
+
+static const char *nid_name(int nid)
+{
+    const char *name = OBJ_nid2ln(nid);
+
+    if (name == NULL)
+        name = OBJ_nid2sn(nid);
+    if (name == NULL)
+        name = "<unknown OID>";
+    return name;
+}
+
 static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs)
 {
     int i, ret = 1;
@@ -2845,6 +2915,12 @@ static int get_opts(int argc, char **argv)
         case OPT_GENINFO:
             opt_geninfo = opt_str();
             break;
+        case OPT_TEMPLATE:
+            opt_template = opt_str();
+            break;
+        case OPT_KEYSPEC:
+            opt_keyspec = opt_str();
+            break;
 
         case OPT_NEWKEY:
             opt_newkey = opt_str();
@@ -3154,6 +3230,71 @@ static int cmp_server(OSSL_CMP_CTX *srv_cmp_ctx)
 }
 #endif
 
+static void print_keyspec(OSSL_CMP_ATAVS *keySpec)
+{
+    const char *desc = "specifications contained in keySpec from genp";
+    BIO *mem;
+    int i;
+    const char *p;
+    long len;
+
+    if (keySpec == NULL) {
+        CMP_info1("No %s", desc);
+        return;
+    }
+
+    mem = BIO_new(BIO_s_mem());
+    if (mem == NULL) {
+        CMP_err1("Out of memory - cannot dump key %s", desc);
+        return;
+    }
+    BIO_printf(mem, "Key %s:\n", desc);
+
+    for (i = 0; i < sk_OSSL_CMP_ATAV_num(keySpec); i++) {
+        OSSL_CMP_ATAV *atav = sk_OSSL_CMP_ATAV_value(keySpec, i);
+        ASN1_OBJECT *type = OSSL_CMP_ATAV_get0_type(atav /* may be NULL */);
+        int nid = OBJ_obj2nid(type);
+
+        switch (nid) {
+        case NID_id_regCtrl_algId:
+            {
+                X509_ALGOR *alg = OSSL_CMP_ATAV_get0_algId(atav);
+                const ASN1_OBJECT *oid;
+                int paramtype;
+                const void *param;
+
+                X509_ALGOR_get0(&oid, &paramtype, &param, alg);
+                BIO_printf(mem, "Key algorithm: ");
+                i2a_ASN1_OBJECT(mem, oid);
+                if (paramtype == V_ASN1_UNDEF || alg->parameter == NULL) {
+                    BIO_printf(mem, "\n");
+                } else {
+                    BIO_printf(mem, " - ");
+                    ASN1_item_print(mem, (ASN1_VALUE *)alg,
+                                    0, ASN1_ITEM_rptr(X509_ALGOR), NULL);
+                }
+            }
+            break;
+        case NID_id_regCtrl_rsaKeyLen:
+            BIO_printf(mem, "Key algorithm: RSA %d\n",
+                       OSSL_CMP_ATAV_get_rsaKeyLen(atav));
+            break;
+        default:
+            BIO_printf(mem, "Invalid key spec: %s\n", nid_name(nid));
+            break;
+        }
+    }
+    BIO_printf(mem, "End of key %s", desc);
+
+    len = BIO_get_mem_data(mem, &p);
+    if (len > INT_MAX)
+        CMP_err1("Info too large - cannot dump key %s", desc);
+    else
+        CMP_info2("%.*s", (int)len, p);
+    BIO_free(mem);
+    return;
+}
+
 static void print_status(void)
 {
     /* print PKIStatusInfo */
@@ -3300,6 +3441,42 @@ static int do_genm(OSSL_CMP_CTX *ctx)
         X509_CRL_free(crl);
         return res;
 
+    } else if (opt_infotype == NID_id_it_certReqTemplate) {
+        OSSL_CRMF_CERTTEMPLATE *certTemplate;
+        OSSL_CMP_ATAVS *keySpec;
+        int res = 0;
+
+        if (!OSSL_CMP_get1_certReqTemplate(ctx, &certTemplate, &keySpec))
+            return 0;
+
+        if (certTemplate == NULL) {
+            CMP_warn("no certificate request template available");
+            if (!delete_file(opt_template, "certTemplate from genp"))
+                return 0;
+            if (opt_keyspec != NULL
+                && !delete_file(opt_keyspec, "keySpec from genp"))
+                return 0;
+            return 1;
+        }
+        if (!save_template(opt_template, certTemplate))
+            goto tmpl_end;
+
+        print_keyspec(keySpec);
+        if (opt_keyspec != NULL) {
+            if (keySpec == NULL) {
+                CMP_warn("no key specifications available");
+                if (!delete_file(opt_keyspec, "keySpec from genp"))
+                    goto tmpl_end;
+            } else if (!save_keyspec(opt_keyspec, keySpec)) {
+                goto tmpl_end;
+            }
+        }
+
+        res = 1;
+    tmpl_end:
+        OSSL_CRMF_CERTTEMPLATE_free(certTemplate);
+        sk_OSSL_CMP_ATAV_pop_free(keySpec, OSSL_CMP_ATAV_free);
+        return res;
     } else {
         OSSL_CMP_ITAV *req;
         STACK_OF(OSSL_CMP_ITAV) *itavs;
index b69d29a678d6421e544b5b2a77ef357fa610012a..ce62af2b007aa4e44d4fe24afa7cfa49262726bf 100644 (file)
@@ -451,7 +451,7 @@ static int check_client_crl(const STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList,
 static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
                                         const OSSL_CMP_ITAV *req)
 {
-    OSSL_CMP_ITAV *rsp;
+    OSSL_CMP_ITAV *rsp = NULL;
 
     switch (req_nid) {
     case NID_id_it_caCerts:
@@ -490,6 +490,48 @@ static OSSL_CMP_ITAV *process_genm_itav(mock_srv_ctx *ctx, int req_nid,
                 rsp = OSSL_CMP_ITAV_new_crls(res == 0 ? NULL : ctx->crlOut);
         }
         break;
+    case NID_id_it_certReqTemplate:
+        {
+            OSSL_CRMF_CERTTEMPLATE *reqtemp;
+            OSSL_CMP_ATAVS *keyspec = NULL;
+            X509_ALGOR *keyalg = NULL;
+            OSSL_CMP_ATAV *rsakeylen, *eckeyalg;
+            int ok = 0;
+
+            if ((reqtemp = OSSL_CRMF_CERTTEMPLATE_new()) == NULL)
+                return NULL;
+
+            if (!OSSL_CRMF_CERTTEMPLATE_fill(reqtemp, NULL, NULL,
+                                             X509_get_issuer_name(ctx->refCert),
+                                             NULL))
+                goto crt_err;
+
+            if ((keyalg = X509_ALGOR_new()) == NULL)
+                goto crt_err;
+
+            (void)X509_ALGOR_set0(keyalg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
+                                  V_ASN1_UNDEF, NULL); /* cannot fail */
+
+            eckeyalg = OSSL_CMP_ATAV_new_algId(keyalg);
+            rsakeylen = OSSL_CMP_ATAV_new_rsaKeyLen(4096);
+            ok = OSSL_CMP_ATAV_push1(&keyspec, eckeyalg)
+                 && OSSL_CMP_ATAV_push1(&keyspec, rsakeylen);
+            OSSL_CMP_ATAV_free(eckeyalg);
+            OSSL_CMP_ATAV_free(rsakeylen);
+            X509_ALGOR_free(keyalg);
+
+            if (!ok)
+                goto crt_err;
+
+            rsp = OSSL_CMP_ITAV_new0_certReqTemplate(reqtemp, keyspec);
+            return rsp;
+
+        crt_err:
+            OSSL_CRMF_CERTTEMPLATE_free(reqtemp);
+            OSSL_CMP_ATAVS_free(keyspec);
+            return NULL;
+        }
+        break;
     default:
         rsp = OSSL_CMP_ITAV_dup(req);
     }
index f20e5098ca9ca20a65e5c0a01cbcc07c17c61e42..3bdb3ce688defd86929f05db95950396cd0c265c 100644 (file)
@@ -12,6 +12,7 @@
 #include <openssl/asn1t.h>
 
 #include "cmp_local.h"
+#include "internal/crmf.h"
 
 /* explicit #includes not strictly needed since implied by the above: */
 #include <openssl/cmp.h>
@@ -117,6 +118,9 @@ ASN1_ADB(OSSL_CMP_ITAV) = {
     ADB_ENTRY(NID_id_it_rootCaKeyUpdate,
               ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaKeyUpdate,
                        OSSL_CMP_ROOTCAKEYUPDATE)),
+    ADB_ENTRY(NID_id_it_certReqTemplate,
+              ASN1_OPT(OSSL_CMP_ITAV, infoValue.certReqTemplate,
+                       OSSL_CMP_CERTREQTEMPLATE)),
     ADB_ENTRY(NID_id_it_certProfile,
               ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.certProfile,
                                    ASN1_UTF8STRING)),
@@ -143,6 +147,19 @@ ASN1_SEQUENCE(OSSL_CMP_ROOTCAKEYUPDATE) = {
 } ASN1_SEQUENCE_END(OSSL_CMP_ROOTCAKEYUPDATE)
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
 
+ASN1_ITEM_TEMPLATE(OSSL_CMP_ATAVS) =
+    ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+                          OSSL_CMP_ATAVS, OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_ATAVS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ATAVS)
+
+ASN1_SEQUENCE(OSSL_CMP_CERTREQTEMPLATE) = {
+    ASN1_SIMPLE(OSSL_CMP_CERTREQTEMPLATE, certTemplate, OSSL_CRMF_CERTTEMPLATE),
+    ASN1_SEQUENCE_OF_OPT(OSSL_CMP_CERTREQTEMPLATE, keySpec,
+                         OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(OSSL_CMP_CERTREQTEMPLATE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTREQTEMPLATE)
+
 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),
@@ -358,6 +375,220 @@ int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav,
     return 1;
 }
 
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_certReqTemplate(OSSL_CRMF_CERTTEMPLATE *certTemplate,
+                                    OSSL_CMP_ATAVS *keySpec)
+{
+    OSSL_CMP_ITAV *itav;
+    OSSL_CMP_CERTREQTEMPLATE *tmpl;
+
+    if (certTemplate == NULL && keySpec != NULL) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return NULL;
+    }
+    if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+        return NULL;
+    itav->infoType = OBJ_nid2obj(NID_id_it_certReqTemplate);
+    if (certTemplate == NULL)
+        return itav;
+
+    if ((tmpl = OSSL_CMP_CERTREQTEMPLATE_new()) == NULL) {
+        OSSL_CMP_ITAV_free(itav);
+        return NULL;
+    }
+    itav->infoValue.certReqTemplate = tmpl;
+    tmpl->certTemplate = certTemplate;
+    tmpl->keySpec = keySpec;
+    return itav;
+}
+
+int OSSL_CMP_ITAV_get1_certReqTemplate(const OSSL_CMP_ITAV *itav,
+                                       OSSL_CRMF_CERTTEMPLATE **certTemplate,
+                                       OSSL_CMP_ATAVS **keySpec)
+{
+    OSSL_CMP_CERTREQTEMPLATE *tpl;
+
+    if (itav == NULL || certTemplate == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+
+    *certTemplate = NULL;
+    if (keySpec != NULL)
+        *keySpec = NULL;
+
+    if (OBJ_obj2nid(itav->infoType) != NID_id_it_certReqTemplate) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return 0;
+    }
+    tpl = itav->infoValue.certReqTemplate;
+    if (tpl == NULL) /* no requirements available */
+        return 1;
+
+    if ((*certTemplate = OSSL_CRMF_CERTTEMPLATE_dup(tpl->certTemplate)) == NULL)
+        return 0;
+    if (keySpec != NULL && tpl->keySpec != NULL) {
+        int i, n = sk_OSSL_CMP_ATAV_num(tpl->keySpec);
+
+        *keySpec = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_reserve(NULL, n);
+        if (*keySpec == NULL)
+            goto err;
+        for (i = 0; i < n; i++) {
+            OSSL_CMP_ATAV *atav = sk_OSSL_CMP_ATAV_value(tpl->keySpec, i);
+            ASN1_OBJECT *type = OSSL_CMP_ATAV_get0_type(atav /* may be NULL */);
+            int nid;
+            const char *name;
+
+            if (type == NULL) {
+                ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_KEYSPEC,
+                               "keySpec with index %d in certReqTemplate does not exist",
+                               i);
+                goto err;
+            }
+            nid = OBJ_obj2nid(type);
+
+            if (nid != NID_id_regCtrl_algId
+                    && nid != NID_id_regCtrl_rsaKeyLen) {
+                name = OBJ_nid2ln(nid);
+                if (name == NULL)
+                    name = OBJ_nid2sn(nid);
+                if (name == NULL)
+                    name = "<undef>";
+                ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_KEYSPEC,
+                               "keySpec with index %d in certReqTemplate has invalid type %s",
+                               i, name);
+                goto err;
+            }
+            OSSL_CMP_ATAV_push1(keySpec, atav);
+        }
+    }
+    return 1;
+
+ err:
+    OSSL_CRMF_CERTTEMPLATE_free(*certTemplate);
+    *certTemplate = NULL;
+    sk_OSSL_CMP_ATAV_pop_free(*keySpec, OSSL_CMP_ATAV_free);
+    if (keySpec != NULL)
+        *keySpec = NULL;
+    return 0;
+}
+
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_create(ASN1_OBJECT *type, ASN1_TYPE *value)
+{
+    OSSL_CMP_ATAV *atav;
+
+    if ((atav = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new()) == NULL)
+        return NULL;
+    OSSL_CMP_ATAV_set0(atav, type, value);
+    return atav;
+}
+
+void OSSL_CMP_ATAV_set0(OSSL_CMP_ATAV *atav, ASN1_OBJECT *type,
+                        ASN1_TYPE *value)
+{
+    atav->type = type;
+    atav->value.other = value;
+}
+
+ASN1_OBJECT *OSSL_CMP_ATAV_get0_type(const OSSL_CMP_ATAV *atav)
+{
+    if (atav == NULL)
+        return NULL;
+    return atav->type;
+}
+
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_algId(const X509_ALGOR *alg)
+{
+    X509_ALGOR *dup;
+    OSSL_CMP_ATAV *res;
+
+    if (alg == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return NULL;
+    }
+    if ((dup = X509_ALGOR_dup(alg)) == NULL)
+        return NULL;
+    res = OSSL_CMP_ATAV_create(OBJ_nid2obj(NID_id_regCtrl_algId),
+                               (ASN1_TYPE *)dup);
+    if (res == NULL)
+        X509_ALGOR_free(dup);
+    return res;
+}
+
+X509_ALGOR *OSSL_CMP_ATAV_get0_algId(const OSSL_CMP_ATAV *atav)
+{
+    if (atav == NULL || OBJ_obj2nid(atav->type) != NID_id_regCtrl_algId)
+        return NULL;
+    return atav->value.algId;
+}
+
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_rsaKeyLen(int len)
+{
+    ASN1_INTEGER *aint;
+    OSSL_CMP_ATAV *res = NULL;
+
+    if (len <= 0) {
+        ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+        return NULL;
+    }
+    if ((aint = ASN1_INTEGER_new()) == NULL)
+        return NULL;
+    if (!ASN1_INTEGER_set(aint, len)
+        || (res = OSSL_CMP_ATAV_create(OBJ_nid2obj(NID_id_regCtrl_rsaKeyLen),
+                                       (ASN1_TYPE *)aint)) == NULL)
+        ASN1_INTEGER_free(aint);
+    return res;
+}
+
+int OSSL_CMP_ATAV_get_rsaKeyLen(const OSSL_CMP_ATAV *atav)
+{
+    int64_t val;
+
+    if (atav == NULL || OBJ_obj2nid(atav->type) != NID_id_regCtrl_rsaKeyLen
+            || !ASN1_INTEGER_get_int64(&val, atav->value.rsaKeyLen))
+        return -1;
+    if (val <= 0 || val > INT_MAX)
+        return -2;
+    return (int)val;
+}
+
+ASN1_TYPE *OSSL_CMP_ATAV_get0_value(const OSSL_CMP_ATAV *atav)
+{
+    if (atav == NULL)
+        return NULL;
+    return atav->value.other;
+}
+
+int OSSL_CMP_ATAV_push1(OSSL_CMP_ATAVS **sk_p, const OSSL_CMP_ATAV *atav)
+{
+    int created = 0;
+    OSSL_CMP_ATAV *dup;
+
+    if (sk_p == NULL || atav == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        goto err;
+    }
+
+    if (*sk_p == NULL) {
+        if ((*sk_p = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null()) == NULL)
+            goto err;
+        created = 1;
+    }
+
+    if ((dup = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_dup((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)atav)) == NULL)
+        goto err;
+    if (sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(*sk_p, dup))
+        return 1;
+    OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(dup);
+
+ err:
+    if (created) {
+        sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(*sk_p);
+        *sk_p = NULL;
+    }
+    return 0;
+}
+
 OSSL_CMP_ITAV
 *OSSL_CMP_ITAV_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList)
 {
index 689aa6a9520f71befcd1d112091c2ec63757b979..5cec9438f6145a16bccb08cdfb3125e9794164d2 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_CERTREQTEMPLATE),
+    "generate certreqtemplate"},
     {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_KEYSPEC), "invalid keyspec"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ROOTCAKEYUPDATE),
     "invalid rootcakeyupdate"},
index 17f2f1d3acc5737ea63f50701a2fd0d3f142a348..c68cddad05f0190e076032e09beb78562d508cdb 100644 (file)
@@ -406,3 +406,36 @@ int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
     OSSL_CMP_ITAV_free(itav);
     return res;
 }
+
+int OSSL_CMP_get1_certReqTemplate(OSSL_CMP_CTX *ctx,
+                                  OSSL_CRMF_CERTTEMPLATE **certTemplate,
+                                  OSSL_CMP_ATAVS **keySpec)
+{
+    OSSL_CMP_ITAV *req, *itav = NULL;
+    int res = 0;
+
+    if (keySpec != NULL)
+        *keySpec = NULL;
+    if (certTemplate == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+        return 0;
+    }
+    *certTemplate = NULL;
+
+    if ((req = OSSL_CMP_ITAV_new0_certReqTemplate(NULL, NULL)) == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_GENERATE_CERTREQTEMPLATE);
+        return 0;
+    }
+
+    if ((itav = get_genm_itav(ctx, req, NID_id_it_certReqTemplate,
+                              "certReqTemplate")) == NULL)
+        return 0;
+
+    if (!OSSL_CMP_ITAV_get1_certReqTemplate(itav, certTemplate, keySpec))
+        goto end;
+
+    res = 1;
+ end:
+    OSSL_CMP_ITAV_free(itav);
+    return res;
+}
index 9ebd1858a5574908521ed1c0466247db3827700c..597080379701e501c986fdf6e1df5359d9fb93cd 100644 (file)
@@ -294,6 +294,8 @@ struct ossl_cmp_itav_st {
         X509 *rootCaCert;
         /* NID_id_it_rootCaKeyUpdate - Root CA Certificate Update */
         OSSL_CMP_ROOTCAKEYUPDATE *rootCaKeyUpdate;
+        /* NID_id_it_certReqTemplate - Certificate Request Template */
+        OSSL_CMP_CERTREQTEMPLATE *certReqTemplate;
         /* NID_id_it_crlStatusList -  CRL Update Retrieval */
         STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList;
         /* NID_id_it_crls - Certificate Status Lists */
@@ -800,6 +802,17 @@ struct ossl_cmp_rootcakeyupdate_st {
 } /* OSSL_CMP_ROOTCAKEYUPDATE */;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
 
+/*-
+ * CertReqTemplateContent ::= SEQUENCE {
+ *      certTemplate      CertTemplate,
+ *      keySpec           Controls OPTIONAL
+ * }
+ */
+struct ossl_cmp_certreqtemplate_st {
+    OSSL_CRMF_CERTTEMPLATE *certTemplate;
+    OSSL_CMP_ATAVS *keySpec;
+} /* OSSL_CMP_CERTREQTEMPLATE */;
+
 /* from cmp_asn.c */
 int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
 
index 85b4213934a92240dfb729df5da1eaa2f1244373..55b0c39bf82d674646d05385cddb1a29178e0547 100644 (file)
@@ -146,6 +146,12 @@ ASN1_ADB(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) = {
     ADB_ENTRY(NID_id_regCtrl_protocolEncrKey,
               ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
                           value.protocolEncrKey, X509_PUBKEY)),
+    ADB_ENTRY(NID_id_regCtrl_algId,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.algId, X509_ALGOR)),
+    ADB_ENTRY(NID_id_regCtrl_rsaKeyLen,
+              ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
+                          value.rsaKeyLen, ASN1_INTEGER)),
     ADB_ENTRY(NID_id_regInfo_utf8Pairs,
               ASN1_SIMPLE(OSSL_CRMF_ATTRIBUTETYPEANDVALUE,
                           value.utf8Pairs, ASN1_UTF8STRING)),
@@ -194,6 +200,7 @@ ASN1_SEQUENCE(OSSL_CRMF_CERTTEMPLATE) = {
                              X509_EXTENSION, 9),
 } ASN1_SEQUENCE_END(OSSL_CRMF_CERTTEMPLATE)
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_CERTTEMPLATE)
+IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTTEMPLATE)
 
 ASN1_SEQUENCE(OSSL_CRMF_CERTREQUEST) = {
     ASN1_SIMPLE(OSSL_CRMF_CERTREQUEST, certReqId, ASN1_INTEGER),
index e8937b4231e640f24e0223516be0d5679e0edf70..cfa01ab3992cf1d2f562df480d03ce50594eb061 100644 (file)
@@ -16,6 +16,7 @@
 
 # include <openssl/crmf.h>
 # include <openssl/err.h>
+# include "internal/crmf.h" /* for ossl_crmf_attributetypeandvalue_st */
 
 /* explicit #includes not strictly needed since implied by the above: */
 # include <openssl/types.h>
@@ -335,37 +336,6 @@ struct ossl_crmf_certrequest_st {
 DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTREQUEST)
 DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTREQUEST)
 
-struct ossl_crmf_attributetypeandvalue_st {
-    ASN1_OBJECT *type;
-    union {
-        /* NID_id_regCtrl_regToken */
-        ASN1_UTF8STRING *regToken;
-
-        /* NID_id_regCtrl_authenticator */
-        ASN1_UTF8STRING *authenticator;
-
-        /* NID_id_regCtrl_pkiPublicationInfo */
-        OSSL_CRMF_PKIPUBLICATIONINFO *pkiPublicationInfo;
-
-        /* NID_id_regCtrl_oldCertID */
-        OSSL_CRMF_CERTID *oldCertID;
-
-        /* NID_id_regCtrl_protocolEncrKey */
-        X509_PUBKEY *protocolEncrKey;
-
-        /* NID_id_regInfo_utf8Pairs */
-        ASN1_UTF8STRING *utf8Pairs;
-
-        /* NID_id_regInfo_certReq */
-        OSSL_CRMF_CERTREQUEST *certReq;
-
-        ASN1_TYPE *other;
-    } value;
-} /* OSSL_CRMF_ATTRIBUTETYPEANDVALUE */;
-DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
-DEFINE_STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
-DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
-
 /*-
  * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
  * CertReqMsg ::= SEQUENCE {
index c2bcf98f8bf8b59ae1e981953a6f74f25a0adfcd..3279f49199f8994fe34707935554a103f23ced59 100644 (file)
@@ -234,11 +234,13 @@ 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_CERTREQTEMPLATE:197:generate certreqtemplate
 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_KEYSPEC:202:invalid keyspec
 CMP_R_INVALID_OPTION:174:invalid option
 CMP_R_INVALID_ROOTCAKEYUPDATE:195:invalid rootcakeyupdate
 CMP_R_MISSING_CERTID:165:missing certid
index f84364dba24be8b77fbc777966f0c5b93e51fda2..3a8adb1c66e3e41ffa29d5aa9bad33c638155194 100644 (file)
@@ -1599,6 +1599,10 @@ DEPEND[html/man3/OSSL_CALLBACK.html]=man3/OSSL_CALLBACK.pod
 GENERATE[html/man3/OSSL_CALLBACK.html]=man3/OSSL_CALLBACK.pod
 DEPEND[man/man3/OSSL_CALLBACK.3]=man3/OSSL_CALLBACK.pod
 GENERATE[man/man3/OSSL_CALLBACK.3]=man3/OSSL_CALLBACK.pod
+DEPEND[html/man3/OSSL_CMP_ATAV_set0.html]=man3/OSSL_CMP_ATAV_set0.pod
+GENERATE[html/man3/OSSL_CMP_ATAV_set0.html]=man3/OSSL_CMP_ATAV_set0.pod
+DEPEND[man/man3/OSSL_CMP_ATAV_set0.3]=man3/OSSL_CMP_ATAV_set0.pod
+GENERATE[man/man3/OSSL_CMP_ATAV_set0.3]=man3/OSSL_CMP_ATAV_set0.pod
 DEPEND[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
 GENERATE[html/man3/OSSL_CMP_CTX_new.html]=man3/OSSL_CMP_CTX_new.pod
 DEPEND[man/man3/OSSL_CMP_CTX_new.3]=man3/OSSL_CMP_CTX_new.pod
@@ -3379,6 +3383,7 @@ html/man3/OPENSSL_secure_malloc.html \
 html/man3/OPENSSL_strcasecmp.html \
 html/man3/OSSL_ALGORITHM.html \
 html/man3/OSSL_CALLBACK.html \
+html/man3/OSSL_CMP_ATAV_set0.html \
 html/man3/OSSL_CMP_CTX_new.html \
 html/man3/OSSL_CMP_HDR_get0_transactionID.html \
 html/man3/OSSL_CMP_ITAV_new_caCerts.html \
@@ -4036,6 +4041,7 @@ man/man3/OPENSSL_secure_malloc.3 \
 man/man3/OPENSSL_strcasecmp.3 \
 man/man3/OSSL_ALGORITHM.3 \
 man/man3/OSSL_CALLBACK.3 \
+man/man3/OSSL_CMP_ATAV_set0.3 \
 man/man3/OSSL_CMP_CTX_new.3 \
 man/man3/OSSL_CMP_HDR_get0_transactionID.3 \
 man/man3/OSSL_CMP_ITAV_new_caCerts.3 \
index d42666331ad0b09d56b5100732d071d94af1cc05..bf153e579eec60396856b85ac69a5a179f0bb1cf 100644 (file)
@@ -19,6 +19,8 @@ Generic message options:
 [B<-infotype> I<name>]
 [B<-profile> I<name>]
 [B<-geninfo> I<values>]
+[B<-template> I<filename>]
+[B<-keyspec> I<filename>]
 
 Certificate enrollment options:
 
@@ -252,8 +254,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>, C<rootCaCert>
-and C<crlStatusList>.
+There is specific support for C<caCerts>, C<rootCaCert>,  
+C<certReqTemplate>, and C<crlStatusList> (CRL update retrieval).
 
 =item B<-profile> I<name>
 
@@ -268,6 +270,18 @@ Each InfoTypeAndValue gives an OID and an integer or string value
 of the form I<OID>:int:I<number> or I<OID>:str:I<text>,
 e.g., C<'1.2.3.4:int:56789, id-kp:str:name'>.
 
+=item B<-template> I<filename>
+
+The file to save any CRMF certTemplate in DER format
+received in a genp message with id-it-certReqTemplate.
+
+=item B<-keyspec> I<filename>
+
+It is optional and used to specify the file to save any keySpec if
+present in a genp message with id-it-keyGenParameters.
+
+Note: any keySpec field contents received are logged as INFO.
+
 =back
 
 =head2 Certificate enrollment options
diff --git a/doc/man3/OSSL_CMP_ATAV_set0.pod b/doc/man3/OSSL_CMP_ATAV_set0.pod
new file mode 100644 (file)
index 0000000..8ab11df
--- /dev/null
@@ -0,0 +1,118 @@
+=pod
+
+=head1 NAME
+
+OSSL_CMP_ATAV,
+OSSL_CMP_ATAV_create,
+OSSL_CMP_ATAV_set0,
+OSSL_CMP_ATAV_get0_type,
+OSSL_CMP_ATAV_get0_value,
+OSSL_CMP_ATAV_new_algId,
+OSSL_CMP_ATAV_get0_algId,
+OSSL_CMP_ATAV_new_rsaKeyLen,
+OSSL_CMP_ATAV_get_rsaKeyLen,
+OSSL_CMP_ATAVS,
+OSSL_CMP_ATAV_push1,
+OSSL_CMP_ATAV_free
+- OSSL_CMP_ATAV utility functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/cmp.h>
+
+ typedef OSSL_CRMF_ATTRIBUTETYPEANDVALUE OSSL_CMP_ATAV;
+ OSSL_CMP_ATAV *OSSL_CMP_ATAV_create(ASN1_OBJECT *type, ASN1_TYPE *value);
+ void OSSL_CMP_ATAV_set0(OSSL_CMP_ATAV *atav, ASN1_OBJECT *type,
+                         ASN1_TYPE *value);
+ ASN1_OBJECT *OSSL_CMP_ATAV_get0_type(const OSSL_CMP_ATAV *atav);
+ ASN1_TYPE *OSSL_CMP_ATAV_get0_value(const OSSL_CMP_ATAV *atav);
+
+ OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_algId(const X509_ALGOR *alg);
+ X509_ALGOR *OSSL_CMP_ATAV_get0_algId(const OSSL_CMP_ATAV *atav);
+ OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_rsaKeyLen(int len);
+ int OSSL_CMP_ATAV_get_rsaKeyLen(const OSSL_CMP_ATAV *atav);
+
+ typedef STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) OSSL_CMP_ATAVS;
+ int OSSL_CMP_ATAV_push1(OSSL_CMP_ATAVS **sk_p, const OSSL_CMP_ATAV *atav);
+ void OSSL_CMP_ATAV_free(OSSL_CMP_ATAV *atav);
+
+=head1 DESCRIPTION
+
+B<OSSL_CMP_ATAV> is a short hand of B<OSSL_CRMF_ATTRIBUTETYPEANDVALUE>,
+defined in RFC 4211 Appendix B.
+It is typically used in CertRequest structures,
+but also in CertReqTemplateContent structures for key specifications.
+
+OSSL_CMP_ATAV_create() creates a new B<OSSL_CMP_ATAV> structure and fills it in.
+It combines OSSL_CMP_ATAV_new() and OSSL_CMP_ATAV_set0().
+
+OSSL_CMP_ATAV_set0() sets the I<atav> with an infoType of I<type> and an
+infoValue of I<value>.
+The pointers I<type> and I<value> may be NULL, otherwise
+they must B<not> be freed up after the call because their ownership
+is transferred to I<atav>. The I<itav> pointer must not be NULL.
+
+OSSL_CMP_ATAV_get0_type() returns a direct pointer to the infoType
+in the I<atav> unless it is NULL.
+
+OSSL_CMP_ATAV_get0_value() returns a direct pointer to the infoValue
+in the I<atav> as generic B<ASN1_TYPE> pointer unless I<atav> is NULL.
+
+OSSL_CMP_ATAV_new_algId() creates a new B<OSSL_CMP_ATAV> structure of type
+B<algId> and fills it in with a copy of the given I<alg>.
+
+OSSL_CMP_ATAV_get0_algId() returns
+a direct pointer to the algId infoValue in the I<atav> of type B<X509_ALGOR>
+or NULL if I<atav> is NULL or does not contain an algId.
+
+OSSL_CMP_ATAV_new_rsaKeyLen() creates a new B<OSSL_CMP_ATAV> structure of type
+B<rsaKeyLen> and fills it in with the given I<len>, which must be positive.
+
+OSSL_CMP_ATAV_get_rsaKeyLen() returns
+the RSA key length in rsaKeyLen infoValue in the I<atav>,
+-1 if I<atav> is NULL or does not contain an rsaKeyLen or cannot be parsed,
+or -2 if the value is less than 1 or is greater than INT_MAX.
+
+OSSL_CMP_ATAV_push1() pushes a copy of I<atav> to the stack of B<OSSL_CMP_ATAV>
+pointed to by I<*sk_p>. It creates a new stack if I<*sk_p> points to NULL.
+
+OSSL_CMP_ATAV_free() deallocates I<atav>. It is defined as a macro.
+
+=head1 NOTES
+
+CMP is defined in RFC 4210. CRMF is defined in RFC 4211.
+
+=head1 RETURN VALUES
+
+OSSL_CMP_ATAV_create(),
+OSSL_CMP_ATAV_new_algId(), and OSSL_CMP_ATAV_new_rsaKeyLen()
+return a pointer to the ATAV structure on success, or NULL on error.
+
+OSSL_CMP_ATAV_set0() and OSSL_CMP_ATAV_free() do not return a value.
+
+OSSL_CMP_ATAV_get0_type(), OSSL_CMP_ATAV_get0_value(), and
+OSSL_CMP_ATAV_get0_algId()
+return the respective pointer or NULL if their input is NULL.
+
+OSSL_CMP_ATAV_get_rsaKeyLen() return a key length in bits or < 0 on error.
+
+OSSL_CMP_ATAV_push1() returns 1 on success, 0 on error.
+
+=head1 SEE ALSO
+
+L<OSSL_CMP_ITAV_new0_certReqTemplate(3)>, L<ASN1_TYPE_set(3)>
+
+=head1 HISTORY
+
+The B<OSSL_CMP_ATAV> type and related functions were added in OpenSSL 3.4.
+
+=head1 COPYRIGHT
+
+Copyright 2022 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 209c56929e2e320846b34daabc1b36c437076a4a..6fc1cf6f4f0ea38a83ca63ad1f84c36772fc0860 100644 (file)
@@ -14,7 +14,9 @@ OSSL_CMP_CRLSTATUS_get0,
 OSSL_CMP_ITAV_new0_crlStatusList,
 OSSL_CMP_ITAV_get0_crlStatusList,
 OSSL_CMP_ITAV_new_crls,
-OSSL_CMP_ITAV_get0_crls
+OSSL_CMP_ITAV_get0_crls,
+OSSL_CMP_ITAV_new0_certReqTemplate,
+OSSL_CMP_ITAV_get1_certReqTemplate
 - CMP utility functions for handling specific genm and genp messages
 
 =head1 SYNOPSIS
@@ -48,6 +50,12 @@ OSSL_CMP_ITAV_get0_crls
                                       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);
+ OSSL_CMP_ITAV
+ *OSSL_CMP_ITAV_new0_certReqTemplate(OSSL_CRMF_CERTTEMPLATE *certTemplate,
+                                     OSSL_CMP_ATAVS *keySpec);
+ int OSSL_CMP_ITAV_get1_certReqTemplate(const OSSL_CMP_ITAV *itav,
+                                        OSSL_CRMF_CERTTEMPLATE **certTemplate,
+                                        OSSL_CMP_ATAVS **keySpec);
 
 =head1 DESCRIPTION
 
@@ -100,6 +108,27 @@ 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:
 
+OSSL_CMP_ITAV_new0_certReqTemplate() creates an B<OSSL_CMP_ITAV> structure
+of type B<certReqTemplate>.
+If I<certTemplate> is NULL then also I<keySpec> must be NULL,
+and the resulting ITAV can be used in a B<genm> message to obtain the
+requirements a PKI has on the certificate template used to request certificates,
+or in a B<genp> message stating that there are no such requirements.
+Otherwise the resulting ITAV includes a CertReqTemplateValue structure
+with I<certTemplate> of type B<OSSL_CRMF_CERTTEMPLATE> and an optional list
+of key specifications I<keySpec>, each being of type B<OSSL_CMP_ATAV>, and
+the resulting ATAV can be used in a B<genp> message to provide requirements.
+
+OSSL_CMP_ITAV_get1_certReqTemplate()
+requires that I<itav> has type B<certReqTemplate>.
+If assigns NULL to I<*certTemplate> if no B<OSSL_CRMF_CERTTEMPLATE> structure
+with a certificate template value is in I<itav>,
+otherwise a copy of the certTemplate field value.
+If I<keySpec> is not NULL, it is assigned NULL
+if the structure is not present in I<itav> or the keySpec field is absent.
+Otherwise, the function checks that all elements of keySpec field are of type
+B<algId> or B<rsaKeyLen> and assigns to I<*keySpec> a copy of the keySpec field.
+
 =over 4
 
 =item the list of distribution points in the first cRLDistributionPoints
@@ -150,13 +179,14 @@ CMP is defined in RFC 4210.
 
 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()
+OSSL_CMP_CRLSTATUS_create(), OSSL_CMP_ITAV_new0_crlStatusList(),
+OSSL_CMP_ITAV_new_crls() and OSSL_CMP_ITAV_new0_certReqTemplate()
 return a pointer to the new ITAV structure on success, or NULL on error.
 
 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()
+OSSL_CMP_ITAV_get0_crlStatusList(), OSSL_CMP_ITAV_get0_crls()
+and OSSL_CMP_ITAV_get1_certReqTemplate()
 return 1 on success, 0 on error.
 
 =head1 SEE ALSO
@@ -172,8 +202,9 @@ 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.4.
+OSSL_CMP_ITAV_get0_crlStatusList(), OSSL_CMP_ITAV_new_crls(),
+OSSL_CMP_ITAV_get0_crls(), OSSL_CMP_ITAV_new0_certReqTemplate()
+and OSSL_CMP_ITAV_get1_certReqTemplate() were added in OpenSSL 3.4.
 
 =head1 COPYRIGHT
 
index a264ec88275ad2e42fa4138352ffe92347274896..c1428be90e1d1dd237cc78b87e8ba793af79a486 100644 (file)
@@ -16,7 +16,8 @@ OSSL_CMP_exec_RR_ses,
 OSSL_CMP_exec_GENM_ses,
 OSSL_CMP_get1_caCerts,
 OSSL_CMP_get1_rootCaKeyUpdate,
-OSSL_CMP_get1_crlUpdate
+OSSL_CMP_get1_crlUpdate,
+OSSL_CMP_get1_certReqTemplate
 - functions implementing CMP client transactions
 
 =head1 SYNOPSIS
@@ -45,7 +46,9 @@ OSSL_CMP_get1_crlUpdate
  int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
                              const X509_CRL *last_crl,
                              X509_CRL **crl);
-
+ int OSSL_CMP_get1_certReqTemplate(OSSL_CMP_CTX *ctx,
+                                   OSSL_CRMF_CERTTEMPLATE **certTemplate,
+                                   OSSL_CMP_ATAVS **keySpec);
 =head1 DESCRIPTION
 
 This is the OpenSSL API for doing CMP (Certificate Management Protocol)
@@ -169,6 +172,15 @@ 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.
 
+OSSL_CMP_get1_certReqTemplate() uses a genm request message with
+infoType certReqTemplate to obtain a certificate request template from the
+CMP server referenced by I<ctx>. On success it assigns to I<*certTemplate>
+the certificate template received. NULL output means that no certificate
+request template was provided by the server.
+The optional I<keySpec> output parameter is assigned the key specification
+if received, otherwise it set to NULL.
+Both must be freed by the caller.
+
 =head1 NOTES
 
 CMP is defined in RFC 4210 (and CRMF in RFC 4211).
@@ -205,7 +217,8 @@ 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(),
-OSSL_CMP_get1_rootCaKeyUpdate() and OSSL_CMP_get1_crlUpdate()
+OSSL_CMP_get1_rootCaKeyUpdate(), OSSL_CMP_get1_crlUpdate()
+and OSSL_CMP_get1_certReqTemplate()
 return 1 on success, 0 on error.
 
 OSSL_CMP_exec_GENM_ses() returns NULL on error,
@@ -235,7 +248,8 @@ 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() was added in OpenSSL 3.4.
+OSSL_CMP_get1_crlUpdate() and OSSL_CMP_get1_certReqTemplate()
+were added in OpenSSL 3.4.
 
 =head1 COPYRIGHT
 
index d0769ac61b490438b9e25a988df5ccb534be3036..9d57719a485ab12e9e64b14b6b8aa3b3705e650d 100644 (file)
@@ -41,7 +41,6 @@ OSSL_CRMF_MSG_get_certReqId
 
  int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm);
 
-
 =head1 DESCRIPTION
 
 OSSL_CRMF_MSG_get0_tmpl() retrieves the certificate template of I<crm>.
index 6333ba698585f43dfe3bf19983ed88c867a89cd6..dc43c46aa9ab9f7888594a6094c0ae477df994ff 100644 (file)
@@ -136,6 +136,9 @@ OCSP_SIGNATURE_free,
 OCSP_SIGNATURE_new,
 OCSP_SINGLERESP_free,
 OCSP_SINGLERESP_new,
+OSSL_CMP_ATAVS_new,
+OSSL_CMP_ATAVS_free,
+OSSL_CMP_ATAVS_it,
 OSSL_CMP_CRLSTATUS_free,
 OSSL_CMP_ITAV_dup,
 OSSL_CMP_ITAV_free,
@@ -157,6 +160,9 @@ OSSL_CRMF_CERTID_new,
 OSSL_CRMF_CERTTEMPLATE_free,
 OSSL_CRMF_CERTTEMPLATE_it,
 OSSL_CRMF_CERTTEMPLATE_new,
+OSSL_CRMF_CERTTEMPLATE_dup,
+OSSL_CRMF_ATTRIBUTETYPEANDVALUE_dup,
+OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free,
 OSSL_CRMF_ENCRYPTEDVALUE_free,
 OSSL_CRMF_ENCRYPTEDVALUE_it,
 OSSL_CRMF_ENCRYPTEDVALUE_new,
index 373962e135161cd824ae0baad87e6053545b459c..38181e764bb4371ef48f599fa5bf2ac61505cfba 100644 (file)
@@ -89,6 +89,7 @@ d2i_OCSP_REVOKEDINFO,
 d2i_OCSP_SERVICELOC,
 d2i_OCSP_SIGNATURE,
 d2i_OCSP_SINGLERESP,
+d2i_OSSL_CMP_ATAVS,
 d2i_OSSL_CMP_MSG,
 d2i_OSSL_CMP_PKIHEADER,
 d2i_OSSL_CMP_PKISI,
@@ -270,6 +271,7 @@ i2d_OCSP_REVOKEDINFO,
 i2d_OCSP_SERVICELOC,
 i2d_OCSP_SIGNATURE,
 i2d_OCSP_SINGLERESP,
+i2d_OSSL_CMP_ATAVS,
 i2d_OSSL_CMP_MSG,
 i2d_OSSL_CMP_PKIHEADER,
 i2d_OSSL_CMP_PKISI,
diff --git a/include/internal/crmf.h b/include/internal/crmf.h
new file mode 100644 (file)
index 0000000..9e37320
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019-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
+ * https://www.openssl.org/source/license.html
+ */
+#ifndef OSSL_CRYPTO_CRMF_H
+# define OSSL_CRYPTO_CRMF_H
+# pragma once
+
+# include <openssl/crmf.h>
+
+struct ossl_crmf_attributetypeandvalue_st {
+    ASN1_OBJECT *type;
+    union {
+        /* NID_id_regCtrl_regToken */
+        ASN1_UTF8STRING *regToken;
+
+        /* NID_id_regCtrl_authenticator */
+        ASN1_UTF8STRING *authenticator;
+
+        /* NID_id_regCtrl_pkiPublicationInfo */
+        OSSL_CRMF_PKIPUBLICATIONINFO *pkiPublicationInfo;
+
+        /* NID_id_regCtrl_oldCertID */
+        OSSL_CRMF_CERTID *oldCertID;
+
+        /* NID_id_regCtrl_protocolEncrKey */
+        X509_PUBKEY *protocolEncrKey;
+
+        /* NID_id_regCtrl_algId */
+        X509_ALGOR *algId;
+
+        /* NID_id_regCtrl_rsaKeyLen */
+        ASN1_INTEGER *rsaKeyLen;
+
+        /* NID_id_regInfo_utf8Pairs */
+        ASN1_UTF8STRING *utf8Pairs;
+
+        /* NID_id_regInfo_certReq */
+        OSSL_CRMF_CERTREQUEST *certReq;
+
+        ASN1_TYPE *other;
+    } value;
+} /* OSSL_CRMF_ATTRIBUTETYPEANDVALUE */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+
+#endif /* OSSL_CRYPTO_CRMF_H */
index c46b9ab594fa7f9fdacfbe20a9f455b4de9ba552..d659331fa38fa7a6c8042a001d0c55213feb3e9b 100644 (file)
@@ -234,6 +234,16 @@ typedef struct ossl_cmp_crlstatus_st OSSL_CMP_CRLSTATUS;
     generate_stack_macros("OSSL_CMP_CRLSTATUS");
 -}
 
+typedef OSSL_CRMF_ATTRIBUTETYPEANDVALUE OSSL_CMP_ATAV;
+#  define OSSL_CMP_ATAV_free OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free
+typedef STACK_OF(OSSL_CRMF_ATTRIBUTETYPEANDVALUE) OSSL_CMP_ATAVS;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ATAVS)
+#  define stack_st_OSSL_CMP_ATAV stack_st_OSSL_CRMF_ATTRIBUTETYPEANDVALUE
+#  define sk_OSSL_CMP_ATAV_num sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_num
+#  define sk_OSSL_CMP_ATAV_value sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_value
+#  define sk_OSSL_CMP_ATAV_push sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push
+#  define sk_OSSL_CMP_ATAV_pop_free sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_pop_free
+
 typedef struct ossl_cmp_revrepcontent_st OSSL_CMP_REVREPCONTENT;
 typedef struct ossl_cmp_pkisi_st OSSL_CMP_PKISI;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
@@ -299,6 +309,23 @@ 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);
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_certReqTemplate(OSSL_CRMF_CERTTEMPLATE *certTemplate,
+                                    OSSL_CMP_ATAVS *keySpec);
+int OSSL_CMP_ITAV_get1_certReqTemplate(const OSSL_CMP_ITAV *itav,
+                                       OSSL_CRMF_CERTTEMPLATE **certTemplate,
+                                       OSSL_CMP_ATAVS **keySpec);
+
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_create(ASN1_OBJECT *type, ASN1_TYPE *value);
+void OSSL_CMP_ATAV_set0(OSSL_CMP_ATAV *itav, ASN1_OBJECT *type,
+                        ASN1_TYPE *value);
+ASN1_OBJECT *OSSL_CMP_ATAV_get0_type(const OSSL_CMP_ATAV *itav);
+ASN1_TYPE *OSSL_CMP_ATAV_get0_value(const OSSL_CMP_ATAV *itav);
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_algId(const X509_ALGOR *alg);
+X509_ALGOR *OSSL_CMP_ATAV_get0_algId(const OSSL_CMP_ATAV *atav);
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_rsaKeyLen(int len);
+int OSSL_CMP_ATAV_get_rsaKeyLen(const OSSL_CMP_ATAV *atav);
+int OSSL_CMP_ATAV_push1(OSSL_CMP_ATAVS **sk_p, const OSSL_CMP_ATAV *atav);
 
 void OSSL_CMP_MSG_free(OSSL_CMP_MSG *msg);
 
@@ -546,6 +573,9 @@ int OSSL_CMP_get1_rootCaKeyUpdate(OSSL_CMP_CTX *ctx,
 int OSSL_CMP_get1_crlUpdate(OSSL_CMP_CTX *ctx, const X509 *crlcert,
                             const X509_CRL *last_crl,
                             X509_CRL **crl);
+int OSSL_CMP_get1_certReqTemplate(OSSL_CMP_CTX *ctx,
+                                  OSSL_CRMF_CERTTEMPLATE **certTemplate,
+                                  OSSL_CMP_ATAVS **keySpec);
 
 #  ifdef  __cplusplus
 }
index 700ffbeb7beb622156b068845d4ba473a80c5016..d196924f74767121ec6c98744f2ed65d8c6a50cc 100644 (file)
 #  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_CERTREQTEMPLATE                   197
 #  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_KEYSPEC                            202
 #  define CMP_R_INVALID_OPTION                             174
 #  define CMP_R_INVALID_ROOTCAKEYUPDATE                    195
 #  define CMP_R_MISSING_CERTID                             165
index 43411fa42f66fed2a1389202cd01f2f8861bc964..54a70ebc858e3a494c7a04d03dbce11ac4030920 100644 (file)
@@ -54,6 +54,12 @@ DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_MSG)
     generate_stack_macros("OSSL_CRMF_MSG");
 -}
 typedef struct ossl_crmf_attributetypeandvalue_st OSSL_CRMF_ATTRIBUTETYPEANDVALUE;
+void OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(OSSL_CRMF_ATTRIBUTETYPEANDVALUE *v);
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+{-
+    generate_stack_macros("OSSL_CRMF_ATTRIBUTETYPEANDVALUE");
+-}
+
 typedef struct ossl_crmf_pbmparameter_st OSSL_CRMF_PBMPARAMETER;
 DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_PBMPARAMETER)
 typedef struct ossl_crmf_poposigningkey_st OSSL_CRMF_POPOSIGNINGKEY;
@@ -71,6 +77,7 @@ typedef struct ossl_crmf_singlepubinfo_st OSSL_CRMF_SINGLEPUBINFO;
 DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_SINGLEPUBINFO)
 typedef struct ossl_crmf_certtemplate_st OSSL_CRMF_CERTTEMPLATE;
 DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_CERTTEMPLATE)
+DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTTEMPLATE)
 typedef STACK_OF(OSSL_CRMF_MSG) OSSL_CRMF_MSGS;
 DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_MSGS)
 
index 69dff91b7d80916959521757a6ed874d1b111ffe..26b985bf65d32ad13381c5c6bafa67d24eba7b1a 100644 (file)
@@ -96,6 +96,14 @@ expected,description, -section,val, -cmd,val,val2, -cacertsout,val,val2, -infoty
 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,genm certReqTemplate, -section,, -cmd,genm,, -template,_RESULT_DIR/test.template.der, -keyspec,_RESULT_DIR/test.keyspec.der, -infotype,certReqTemplate,,BLANK,,BLANK,,BLANK,,, -expect_sender, """"
+0,genm certReqTemplate missing template option, -section,, -cmd,genm,, -template,"""", -keyspec,_RESULT_DIR/test.keyspec.der, -infotype,certReqTemplate,,BLANK,,BLANK,
+1,genm certReqTemplate without optional keyspec option, -section,, -cmd,genm,, -template,_RESULT_DIR/test.template.der, -keyspec,"""",, -infotype,certReqTemplate,,BLANK,,BLANK,
+0,genm certReqTemplate missing template arg   , -section,, -cmd,genm,, -template,BLANK, -keyspec,_RESULT_DIR/test.keyspec.der, -infotype,certReqTemplate,,BLANK,,BLANK,
+0,genm certReqTemplate template extra arg     , -section,, -cmd,genm,, -template,_RESULT_DIR/test.template.der,_RESULT_DIR/test.template.der, -infotype,certReqTemplate,,BLANK,,BLANK,
+0,genm certReqTemplate template arg non-ex dir, -section,, -cmd,genm,, -template,idontexist/idontexist,, -infotype,certReqTemplate,,BLANK,,BLANK,
+0,genm certReqTemplate keyspec arg non-ex dir, -section,, -cmd,genm,, -template,_RESULT_DIR/test.template.der, -keyspec,idontexist/idontexist,, -infotype,certReqTemplate,,BLANK,,BLANK,
+,,,,,,,,,,,,,,,,,,,,,,
 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 526cc59355dcec9e32d8fb3a0f21b18eed6cd9a0..681183a9f4c58e01c9bd3eded0c044b7bcd288b7 100644 (file)
@@ -5559,6 +5559,26 @@ OSSL_CMP_ITAV_get0_crls                 ?        3_4_0   EXIST::FUNCTION:CMP
 OSSL_CMP_ITAV_new0_crlStatusList        ?      3_4_0   EXIST::FUNCTION:CMP
 OSSL_CMP_ITAV_new_crls                  ?      3_4_0   EXIST::FUNCTION:CMP
 OSSL_CMP_get1_crlUpdate                 ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_new0_certReqTemplate      ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ITAV_get1_certReqTemplate      ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_create                    ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_set0                      ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_get0_type                 ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_get0_value                ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_new_algId                 ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_get0_algId                ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_new_rsaKeyLen             ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_get_rsaKeyLen             ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAV_push1                     ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_get1_certReqTemplate           ?      3_4_0   EXIST::FUNCTION:CMP
+d2i_OSSL_CMP_ATAVS                      ?      3_4_0   EXIST::FUNCTION:CMP
+i2d_OSSL_CMP_ATAVS                      ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAVS_free                     ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAVS_new                      ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CMP_ATAVS_it                       ?      3_4_0   EXIST::FUNCTION:CMP
+OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free    ?      3_4_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_ATTRIBUTETYPEANDVALUE_dup     ?      3_4_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_CERTTEMPLATE_dup              ?      3_4_0   EXIST::FUNCTION:CRMF
 CRYPTO_atomic_store                     ?      3_4_0   EXIST::FUNCTION:
 CRYPTO_aligned_alloc                    ?      3_4_0   EXIST::FUNCTION:
 d2i_X509_ACERT                          ?      3_4_0   EXIST::FUNCTION:
index acb7f5f1d8c0304d9f2d02829a81a04c182346b1..143b3a33d1a3888436b5622fd925acf4c697da9f 100644 (file)
@@ -461,6 +461,9 @@ OSSL_CMP_LOG_WARNING                    define
 OSSL_CMP_MSTR_HELPER                    define
 OSSL_CMP_MSTR                           define
 OSSL_CMP_P10CR                          define
+OSSL_CMP_ATAV                           define
+OSSL_CMP_ATAV_free                      define
+OSSL_CMP_ATAVS                          define
 OSSL_CMP_certConf_cb_t                  datatype
 OSSL_CMP_log_cb_t                       datatype
 OSSL_CMP_severity                       datatype