]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
CMP: add support for central key generation
authorRajeev Ranjan <ranjan.rajeev@siemens.com>
Wed, 29 May 2024 16:19:29 +0000 (18:19 +0200)
committerTomas Mraz <tomas@openssl.org>
Mon, 27 Jan 2025 07:56:46 +0000 (08:56 +0100)
- add testcase for central keygen
- add documentation

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/25132)

37 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_client.c
crypto/cmp/cmp_err.c
crypto/cmp/cmp_local.h
crypto/cmp/cmp_msg.c
crypto/cmp/cmp_protect.c
crypto/cmp/cmp_server.c
crypto/cms/cms_asn1.c
crypto/cms/cms_lib.c
crypto/crmf/crmf_asn.c
crypto/crmf/crmf_err.c
crypto/crmf/crmf_lib.c
crypto/crmf/crmf_local.h
crypto/err/openssl.txt
doc/internal/man3/ossl_cms_sign_encrypt.pod [new file with mode: 0644]
doc/man1/openssl-cmp.pod.in
doc/man3/CMS_EnvelopedData_create.pod
doc/man3/OSSL_CMP_CTX_new.pod
doc/man3/OSSL_CRMF_MSG_get0_tmpl.pod
doc/man3/X509_VERIFY_PARAM_set_flags.pod
doc/man3/X509_check_purpose.pod
doc/man3/X509_dup.pod
doc/man3/d2i_X509.pod
include/internal/cms.h [new file with mode: 0644]
include/openssl/cmperr.h
include/openssl/cms.h.in
include/openssl/crmf.h.in
include/openssl/crmferr.h
test/recipes/80-test_cmp_http.t
test/recipes/80-test_cmp_http_data/Mock/server.cnf
test/recipes/80-test_cmp_http_data/Mock/server.crt
test/recipes/80-test_cmp_http_data/test_commands.csv
util/libcrypto.num

index 1369f5d826a119374b1015055d8f1045629331d2..51d17b3a9b6a66af60e71c2da8061e8b95e409d6 100644 (file)
@@ -85,6 +85,12 @@ OpenSSL 3.5
 
    *David von Oheimb*
 
+ * Added support for central key generation in CMP.
+
+   This work was sponsored by Siemens AG.
+
+   *Rajeev Ranjan*
+
  * Optionally allow the FIPS provider to use the `JITTER` entropy source.
    Note that using this option will require the resulting FIPS provider
    to undergo entropy source validation [ESV] by the [CMVP], without this
index 3fa7dd936187ed48dd136f433661b9908df227e5..c33745cdddc80e1e817765b648127be416bcfda9 100644 (file)
@@ -124,6 +124,8 @@ static char *opt_profile = NULL;
 /* certificate enrollment */
 static char *opt_newkey = NULL;
 static char *opt_newkeypass = NULL;
+static int opt_centralkeygen = 0;
+static char *opt_newkeyout = NULL;
 static char *opt_subject = NULL;
 static int opt_days = 0;
 static char *opt_reqexts = NULL;
@@ -199,6 +201,8 @@ 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_key = NULL;
+static char *opt_rsp_keypass = NULL;
 static char *opt_rsp_crl = NULL;
 static char *opt_rsp_extracerts = NULL;
 static char *opt_rsp_capubs = NULL;
@@ -230,7 +234,8 @@ typedef enum OPTION_choice {
     OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO,
     OPT_TEMPLATE, OPT_KEYSPEC,
 
-    OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT,
+    OPT_NEWKEY, OPT_NEWKEYPASS, OPT_CENTRALKEYGEN,
+    OPT_NEWKEYOUT, OPT_SUBJECT,
     OPT_DAYS, OPT_REQEXTS,
     OPT_SANS, OPT_SAN_NODEFAULT,
     OPT_POLICIES, OPT_POLICY_OIDS, OPT_POLICY_OIDS_CRITICAL,
@@ -282,7 +287,8 @@ 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_CRL, OPT_RSP_EXTRACERTS, OPT_RSP_CAPUBS,
+    OPT_REF_CERT, OPT_RSP_CERT, OPT_RSP_KEY, OPT_RSP_KEYPASS,
+    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,
@@ -326,6 +332,10 @@ const OPTIONS cmp_options[] = {
     {"newkey", OPT_NEWKEY, 's',
      "Private or public key for the requested cert. Default: CSR key or client key"},
     {"newkeypass", OPT_NEWKEYPASS, 's', "New private key pass phrase source"},
+    {"centralkeygen", OPT_CENTRALKEYGEN, '-',
+     "Request central (server-side) key generation. Default is local generation"},
+    {"newkeyout", OPT_NEWKEYOUT, 's',
+     "File to save centrally generated key, in PEM format"},
     {"subject", OPT_SUBJECT, 's',
      "Distinguished Name (DN) of subject to use in the requested cert template"},
     {OPT_MORE_STR, 0, 0,
@@ -571,6 +581,12 @@ 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_key", OPT_RSP_KEY, 's',
+     "Private key for the certificate to be returned as mock enrollment result"},
+    {OPT_MORE_STR, 0, 0,
+     "Key to be returned for central key pair generation"},
+    {"rsp_keypass", OPT_RSP_KEYPASS, 's',
+     "Response private key (and cert) pass phrase source"},
     {"rsp_crl", OPT_RSP_CRL, 's',
      "CRL to be returned in genp of type crls"},
     {"rsp_extracerts", OPT_RSP_EXTRACERTS, 's',
@@ -630,8 +646,8 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */
     {&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},
+    {&opt_newkey}, {&opt_newkeypass}, {(char **)&opt_centralkeygen},
+    {&opt_newkeyout}, {&opt_subject}, {(char **)&opt_days}, {&opt_reqexts},
     {&opt_sans}, {(char **)&opt_san_nodefault},
     {&opt_policies}, {&opt_policy_oids}, {(char **)&opt_policy_oids_critical},
     {(char **)&opt_popo}, {&opt_csr},
@@ -683,8 +699,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_crl},
-    {&opt_rsp_extracerts}, {&opt_rsp_capubs},
+    {&opt_ref_cert}, {&opt_rsp_cert}, {&opt_rsp_key}, {&opt_rsp_keypass},
+    {&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},
@@ -1197,11 +1213,25 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
     if (opt_rsp_cert == NULL) {
         CMP_warn("no -rsp_cert given for mock server");
     } else {
-        if (!setup_cert(srv_ctx, opt_rsp_cert, opt_keypass,
+        if (!setup_cert(srv_ctx, opt_rsp_cert, opt_rsp_keypass,
                         "cert the mock server returns on certificate requests",
                         (add_X509_fn_t)ossl_cmp_mock_srv_set1_certOut))
             goto err;
     }
+    if (opt_rsp_key != NULL) {
+        EVP_PKEY *pkey = load_key_pwd(opt_rsp_key, opt_keyform,
+                                      opt_rsp_keypass, engine,
+                                      "private key for enrollment cert");
+
+        if (pkey == NULL
+            || !ossl_cmp_mock_srv_set1_keyOut(srv_ctx, pkey)) {
+            EVP_PKEY_free(pkey);
+            goto err;
+        }
+        EVP_PKEY_free(pkey);
+    }
+    cleanse(opt_rsp_keypass);
+
     if (!setup_mock_crlout(srv_ctx, opt_rsp_crl,
                            "CRL to be returned by the mock server"))
         goto err;
@@ -1672,11 +1702,27 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
     if (!set_name(opt_issuer, OSSL_CMP_CTX_set1_issuer, ctx, "issuer"))
         return 0;
     if (opt_cmd == CMP_IR || opt_cmd == CMP_CR || opt_cmd == CMP_KUR) {
-        if (opt_reqin == NULL && opt_newkey == NULL
+        if (opt_reqin == NULL && opt_newkey == NULL && !opt_centralkeygen
             && opt_key == NULL && opt_csr == NULL && opt_oldcert == NULL) {
-            CMP_err("missing -newkey (or -key) to be certified and no -csr, -oldcert, -cert, or -reqin option given, which could provide fallback public key");
+            CMP_err("missing -newkey (or -key) to be certified and no -csr, -oldcert, -cert, or -reqin option given, which could provide fallback public key."
+                    " Neither central key generation is requested.");
             return 0;
         }
+        if (opt_popo == OSSL_CRMF_POPO_NONE && !opt_centralkeygen) {
+            CMP_info("POPO is disabled, which implies -centralkeygen");
+            opt_centralkeygen = 1;
+        }
+        if (opt_centralkeygen) {
+            if (opt_popo > OSSL_CRMF_POPO_NONE) {
+                CMP_err1("-popo value %d is inconsistent with -centralkeygen", opt_popo);
+                return 0;
+            }
+            if (opt_newkeyout == NULL) {
+                CMP_err("-newkeyout not given, nowhere to save centrally generated key");
+                return 0;
+            }
+            opt_popo = OSSL_CRMF_POPO_NONE;
+        }
         if (opt_newkey == NULL
             && opt_popo != OSSL_CRMF_POPO_NONE
             && opt_popo != OSSL_CRMF_POPO_RAVERIFIED) {
@@ -1724,6 +1770,12 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
             CMP_warn1("-policies %s", msg);
         if (opt_policy_oids != NULL)
             CMP_warn1("-policy_oids %s", msg);
+        if (opt_popo != OSSL_CRMF_POPO_NONE - 1)
+            CMP_warn1("-popo %s", msg);
+        if (opt_centralkeygen)
+            CMP_warn1("-popo -1 or -centralkeygen %s", msg);
+        if (opt_newkeyout != NULL)
+            CMP_warn1("-newkeyout %s", msg);
         if (opt_cmd != CMP_P10CR) {
             if (opt_implicit_confirm)
                 CMP_warn1("-implicit_confirm %s, and 'p10cr'", msg);
@@ -1828,13 +1880,14 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
             pkey = load_pubkey(file, format, 0, pass, engine, desc);
             priv = 0;
         }
-        cleanse(opt_newkeypass);
+
         if (pkey == NULL || !OSSL_CMP_CTX_set0_newPkey(ctx, priv, pkey)) {
             EVP_PKEY_free(pkey);
             return 0;
         }
     } else if (opt_reqin != NULL
-               && opt_key == NULL && opt_csr == NULL && opt_oldcert == NULL) {
+               && opt_key == NULL && opt_csr == NULL && opt_oldcert == NULL
+               && !opt_centralkeygen) {
         if (!set_fallback_pubkey(ctx))
             return 0;
     }
@@ -2922,13 +2975,18 @@ static int get_opts(int argc, char **argv)
         case OPT_KEYSPEC:
             opt_keyspec = opt_str();
             break;
-
         case OPT_NEWKEY:
             opt_newkey = opt_str();
             break;
         case OPT_NEWKEYPASS:
             opt_newkeypass = opt_str();
             break;
+        case OPT_CENTRALKEYGEN:
+            opt_centralkeygen = 1;
+            break;
+        case OPT_NEWKEYOUT:
+            opt_newkeyout = opt_str();
+            break;
         case OPT_SUBJECT:
             opt_subject = opt_str();
             break;
@@ -3086,6 +3144,12 @@ static int get_opts(int argc, char **argv)
         case OPT_RSP_CERT:
             opt_rsp_cert = opt_str();
             break;
+        case OPT_RSP_KEY:
+            opt_rsp_key = opt_str();
+            break;
+        case OPT_RSP_KEYPASS:
+            opt_rsp_keypass = opt_str();
+            break;
         case OPT_RSP_CRL:
             opt_rsp_crl = opt_str();
             break;
@@ -3793,6 +3857,34 @@ int cmp_main(int argc, char **argv)
             if (save_free_certs(OSSL_CMP_CTX_get1_caPubs(cmp_ctx),
                                 opt_cacertsout, "CA") < 0)
                 goto err;
+            if (opt_centralkeygen) {
+                EVP_CIPHER *cipher = NULL;
+                char *pass_string = NULL;
+                BIO *out;
+                int result = 1;
+                EVP_PKEY *new_key = OSSL_CMP_CTX_get0_newPkey(cmp_ctx, 1 /* priv */);
+
+                if (new_key == NULL)
+                    goto err;
+                if ((out = bio_open_owner(opt_newkeyout, FORMAT_PEM, 1)) == NULL)
+                    goto err;
+                if (opt_newkeypass != NULL) {
+                    pass_string = get_passwd(opt_newkeypass,
+                                             "Centrally generated private key password");
+                    cipher = EVP_CIPHER_fetch(app_get0_libctx(), SN_aes_256_cbc, app_get0_propq());
+                }
+
+                CMP_info1("saving centrally generated key to file '%s'", opt_newkeyout);
+                if (PEM_write_bio_PrivateKey(out, new_key, cipher, NULL, 0, NULL,
+                                             (void *)pass_string) <= 0)
+                    result = 0;
+
+                BIO_free(out);
+                clear_free(pass_string);
+                EVP_CIPHER_free(cipher);
+                if (!result)
+                    goto err;
+            }
         }
         if (!OSSL_CMP_CTX_reinit(cmp_ctx))
             goto err;
index cddbe8bef5093fdff86fc4cb9844853cbd78d36d..776318fa8baaa02c549b9e6e7060a0bfa7d0990c 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_keyOut(OSSL_CMP_SRV_CTX *srv_ctx, EVP_PKEY *pkey);
 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);
index 5bc166036ec61dc6d9f64ed660c43a24f9b1759a..b35ad0fe9146221b319de72fac37dc398c14c77e 100644 (file)
@@ -19,6 +19,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 */
+    EVP_PKEY *keyOut;          /* Private key to be returned for central keygen */
     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 */
@@ -87,6 +88,21 @@ 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_keyOut(OSSL_CMP_SRV_CTX *srv_ctx, EVP_PKEY *pkey)
+{
+    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 (pkey != NULL && !EVP_PKEY_up_ref(pkey))
+        return 0;
+    EVP_PKEY_free(ctx->keyOut);
+    ctx->keyOut = pkey;
+    return 1;
+}
+
 int ossl_cmp_mock_srv_set1_crlOut(OSSL_CMP_SRV_CTX *srv_ctx,
                                   X509_CRL *crl)
 {
@@ -273,8 +289,9 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
                                             STACK_OF(X509) **caPubs)
 {
     mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
-    int bodytype;
+    int bodytype, central_keygen;
     OSSL_CMP_PKISI *si = NULL;
+    EVP_PKEY *keyOut = NULL;
 
     if (ctx == NULL || cert_req == NULL
             || certOut == NULL || chainOut == NULL || caPubs == NULL) {
@@ -358,6 +375,23 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
             && (*certOut = X509_dup(ctx->certOut)) == NULL)
         /* Should return a cert produced from request template, see FR #16054 */
         goto err;
+
+    central_keygen = OSSL_CRMF_MSG_centralkeygen_requested(crm, p10cr);
+    if (central_keygen < 0)
+        goto err;
+    if (central_keygen == 1
+        && (ctx->keyOut == NULL
+            || (keyOut = EVP_PKEY_dup(ctx->keyOut)) == NULL
+            || !OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_SRV_CTX_get0_cmp_ctx(srv_ctx),
+                                          1 /* priv */, keyOut))) {
+        EVP_PKEY_free(keyOut);
+        goto err;
+    }
+    /*
+     * Note that this uses newPkey to return the private key
+     * and does not check whether the 'popo' field is absent.
+     */
+
     if (ctx->chainOut != NULL
             && (*chainOut = X509_chain_up_ref(ctx->chainOut)) == NULL)
         goto err;
index 13fd6f898d084faf28206a139cf49bf0a43a8618..fa5a3e9831a9b45a7081a4616e6b6c87dc23698a 100644 (file)
@@ -891,7 +891,7 @@ ASN1_CHOICE(OSSL_CMP_CERTORENCCERT) = {
     /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
     ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.certificate, X509, 0),
     ASN1_EXP(OSSL_CMP_CERTORENCCERT, value.encryptedCert,
-             OSSL_CRMF_ENCRYPTEDVALUE, 1),
+             OSSL_CRMF_ENCRYPTEDKEY, 1),
 } ASN1_CHOICE_END(OSSL_CMP_CERTORENCCERT)
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
 
@@ -899,7 +899,7 @@ ASN1_SEQUENCE(OSSL_CMP_CERTIFIEDKEYPAIR) = {
     ASN1_SIMPLE(OSSL_CMP_CERTIFIEDKEYPAIR, certOrEncCert,
                 OSSL_CMP_CERTORENCCERT),
     ASN1_EXP_OPT(OSSL_CMP_CERTIFIEDKEYPAIR, privateKey,
-                 OSSL_CRMF_ENCRYPTEDVALUE, 0),
+                 OSSL_CRMF_ENCRYPTEDKEY, 0),
     ASN1_EXP_OPT(OSSL_CMP_CERTIFIEDKEYPAIR, publicationInfo,
                  OSSL_CRMF_PKIPUBLICATIONINFO, 1)
 } ASN1_SEQUENCE_END(OSSL_CMP_CERTIFIEDKEYPAIR)
index e8fe6f30dcb94ea1dc5c266917df0d70e26a57e8..b88c005c85459849b721266cd4b2b8e5d024b034 100644 (file)
@@ -656,7 +656,7 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
                          ossl_unused int req_type,
                          ossl_unused int expected_type)
 {
-    EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx);
+    EVP_PKEY *rkey = NULL;
     int fail_info = 0; /* no failure */
     const char *txt = NULL;
     OSSL_CMP_CERTREPMESSAGE *crepmsg = NULL;
@@ -748,6 +748,7 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
         return 0;
 
     subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
+    rkey = ossl_cmp_ctx_get0_newPubkey(ctx);
     if (rkey != NULL
         /* X509_check_private_key() also works if rkey is just public key */
             && !(X509_check_private_key(ctx->newCert, rkey))) {
index 5cec9438f6145a16bccb08cdfb3125e9794164d2..2c8cdc18b75635ad3af818428ab5cdc36178c879 100644 (file)
@@ -79,6 +79,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_EXPECTED_POLLREQ), "expected pollreq"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_BUILDING_OWN_CHAIN),
     "failed building own chain"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY),
+     "failed extracting central gen key"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
     "failed extracting pubkey"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILURE_OBTAINING_RANDOM),
@@ -97,6 +99,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ROOTCAKEYUPDATE),
     "invalid rootcakeyupdate"},
+    {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_CENTRAL_GEN_KEY),
+     "missing central gen key"},
     {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"},
@@ -151,6 +155,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
     "transactionid unmatched"},
     {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_CENTRAL_GEN_KEY),
+     "unexpected central gen key"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CERTPROFILE),
     "unexpected certprofile"},
     {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CRLSTATUSLIST),
index 597080379701e501c986fdf6e1df5359d9fb93cd..da616e668a12eae48f44b157e0055eecc3dbfb33 100644 (file)
@@ -311,7 +311,7 @@ typedef struct ossl_cmp_certorenccert_st {
     int type;
     union {
         X509 *certificate;
-        OSSL_CRMF_ENCRYPTEDVALUE *encryptedCert;
+        OSSL_CRMF_ENCRYPTEDKEY *encryptedCert;
     } value;
 } OSSL_CMP_CERTORENCCERT;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
@@ -326,7 +326,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTORENCCERT)
  */
 typedef struct ossl_cmp_certifiedkeypair_st {
     OSSL_CMP_CERTORENCCERT *certOrEncCert;
-    OSSL_CRMF_ENCRYPTEDVALUE *privateKey;
+    OSSL_CRMF_ENCRYPTEDKEY *privateKey;
     OSSL_CRMF_PKIPUBLICATIONINFO *publicationInfo;
 } OSSL_CMP_CERTIFIEDKEYPAIR;
 DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR)
@@ -952,7 +952,8 @@ OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int bodytype,
                                    const OSSL_CRMF_MSG *crm);
 OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
                                    int certReqId, const OSSL_CMP_PKISI *si,
-                                   X509 *cert, const X509 *encryption_recip,
+                                   X509 *cert, const EVP_PKEY *pkey,
+                                   const X509 *encryption_recip,
                                    STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
                                    int unprotectedErrors);
 OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx);
@@ -994,6 +995,7 @@ OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
 int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg);
 
 /* from cmp_protect.c */
+void ossl_cmp_set_own_chain(OSSL_CMP_CTX *ctx);
 int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg);
 ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
                                           const OSSL_CMP_MSG *msg);
index a0b3fb0aea0faebfc66756793dac0498b8d4bc59..952fddf82062f27cf13b243e94ce4c829173fcd2 100644 (file)
@@ -19,6 +19,9 @@
 #include <openssl/crmf.h>
 #include <openssl/err.h>
 #include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/bio.h>
+#include <internal/cms.h>
 
 OSSL_CMP_MSG *OSSL_CMP_MSG_new(OSSL_LIB_CTX *libctx, const char *propq)
 {
@@ -271,6 +274,8 @@ static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, int for_KUR,
 OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
 {
     OSSL_CRMF_MSG *crm = NULL;
+    int central_keygen = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_POPO_METHOD)
+        == OSSL_CRMF_POPO_NONE;
     X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->cert;
     /* refcert defaults to current client cert */
     EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx);
@@ -283,9 +288,10 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
         : X509_get_issuer_name(refcert);
     int crit = ctx->setSubjectAltNameCritical || subject == NULL;
     /* RFC5280: subjectAltName MUST be critical if subject is null */
+    OSSL_CRMF_CERTTEMPLATE *tmpl;
     X509_EXTENSIONS *exts = NULL;
 
-    if (rkey == NULL) {
+    if (rkey == NULL && !central_keygen) {
 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
         ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PUBLIC_KEY);
         return NULL;
@@ -297,6 +303,7 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
     }
     if ((crm = OSSL_CRMF_MSG_new()) == NULL)
         return NULL;
+    tmpl = OSSL_CRMF_MSG_get0_tmpl(crm);
     if (!OSSL_CRMF_MSG_set_certReqId(crm, rid)
             /*
              * fill certTemplate, corresponding to CertificationRequestInfo
@@ -306,6 +313,10 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
             || !OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_MSG_get0_tmpl(crm), rkey,
                                             subject, issuer, NULL /* serial */))
         goto err;
+    if (rkey != NULL && central_keygen)
+        X509_PUBKEY_set0_public_key(OSSL_CRMF_CERTTEMPLATE_get0_publicKey(tmpl),
+                                    NULL, 0);
+
     if (ctx->days != 0) {
         time_t now = time(NULL);
         ASN1_TIME *notBefore = ASN1_TIME_adj(NULL, now, 0, 0);
@@ -441,9 +452,47 @@ OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int type,
     return NULL;
 }
 
+#ifndef OPENSSL_NO_CMS
+static OSSL_CRMF_ENCRYPTEDKEY *enc_privkey(OSSL_CMP_CTX *ctx, const EVP_PKEY *pkey)
+{
+    OSSL_CRMF_ENCRYPTEDKEY *ek = NULL;
+    CMS_EnvelopedData *envData = NULL;
+    BIO *privbio = NULL;
+    EVP_CIPHER *cipher = NULL;
+    X509 *recip = ctx->validatedSrvCert; /* this is the client cert */
+    STACK_OF(X509) *encryption_recips = sk_X509_new_reserve(NULL, 1);
+
+    if (encryption_recips == NULL
+        || !X509_add_cert(encryption_recips, recip, X509_ADD_FLAG_UP_REF))
+        goto err;
+
+    privbio = BIO_new(BIO_s_mem());
+    if (privbio == NULL || i2d_PrivateKey_bio(privbio, pkey) <= 0)
+        goto err;
+    ossl_cmp_set_own_chain(ctx);
+    cipher = EVP_CIPHER_fetch(ctx->libctx, SN_aes_256_cbc, ctx->propq);
+    envData = ossl_cms_sign_encrypt(privbio, ctx->cert, ctx->chain, ctx->pkey, CMS_BINARY,
+                                    encryption_recips, cipher, CMS_BINARY,
+                                    ctx->libctx, ctx->propq);
+    EVP_CIPHER_free(cipher);
+    if (envData == NULL)
+        goto err;
+    ek = OSSL_CRMF_ENCRYPTEDKEY_init_envdata(envData);
+
+ err:
+    sk_X509_pop_free(encryption_recips, X509_free);
+    BIO_free(privbio);
+    if (ek == NULL)
+        M_ASN1_free_of(envData, CMS_EnvelopedData);
+
+    return ek;
+}
+#endif
+
 OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
                                    int certReqId, const OSSL_CMP_PKISI *si,
-                                   X509 *cert, const X509 *encryption_recip,
+                                   X509 *cert, const EVP_PKEY *pkey,
+                                   const X509 *encryption_recip,
                                    STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
                                    int unprotectedErrors)
 {
@@ -487,6 +536,16 @@ OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
         if (!X509_up_ref(cert))
             goto err;
         resp->certifiedKeyPair->certOrEncCert->value.certificate = cert;
+
+        if (pkey != NULL) {
+#ifndef OPENSSL_NO_CMS
+            if ((resp->certifiedKeyPair->privateKey = enc_privkey(ctx, pkey)) == NULL)
+                goto err;
+#else
+            ERR_raise(ERR_LIB_CMP, ERR_R_UNSUPPORTED);
+            goto err;
+#endif
+        }
     }
 
     if (!sk_OSSL_CMP_CERTRESPONSE_push(repMsg->response, resp))
@@ -1042,22 +1101,51 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
 }
 
 /*-
- * Retrieve the newly enrolled certificate from the given certResponse crep.
- * Uses libctx and propq from ctx, in case of indirect POPO also private key.
+ * Retrieve newly enrolled certificate and key from the given certResponse crep.
+ * Stores any centrally generated key in ctx->newPkey.
+ * In case of indirect POPO uses ctx->newPkey to decrypt the new certificate.
  * Returns a pointer to a copy of the found certificate, or NULL if not found.
  */
-X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
-                                      const OSSL_CMP_CERTRESPONSE *crep)
+X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx, const OSSL_CMP_CERTRESPONSE *crep)
 {
     OSSL_CMP_CERTORENCCERT *coec;
     X509 *crt = NULL;
-    EVP_PKEY *pkey;
+    OSSL_CRMF_ENCRYPTEDKEY *encr_key;
+    EVP_PKEY *pkey = NULL;
+    int central_keygen = OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_POPO_METHOD)
+        == OSSL_CRMF_POPO_NONE;
+
+    if (crep->certifiedKeyPair == NULL) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);
+        return NULL;
+    }
+    encr_key = crep->certifiedKeyPair->privateKey;
+    if (encr_key == NULL && central_keygen) {
+        ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_CENTRAL_GEN_KEY);
+        return NULL;
+    }
+    if (encr_key != NULL) {
+        if (!central_keygen) {
+            ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CENTRAL_GEN_KEY);
+            return NULL;
+        }
+        /* found encrypted private key, try to extract */
+        pkey = OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(encr_key, ctx->trusted,
+                                                ctx->untrusted,
+                                                ctx->pkey, ctx->cert,
+                                                ctx->secretValue,
+                                                ctx->libctx, ctx->propq);
+        if (pkey == NULL) {
+            ERR_raise(ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY);
+            return NULL;
+        }
+        OSSL_CMP_CTX_set0_newPkey((OSSL_CMP_CTX *)ctx, 1, pkey);
+    }
 
     if (!ossl_assert(crep != NULL && ctx != NULL))
         return NULL;
 
-    if (crep->certifiedKeyPair
-            && (coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
+    if ((coec = crep->certifiedKeyPair->certOrEncCert) != NULL) {
         switch (coec->type) {
         case OSSL_CMP_CERTORENCCERT_CERTIFICATE:
             crt = X509_dup(coec->value.certificate);
@@ -1070,10 +1158,8 @@ X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
                 ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
                 return NULL;
             }
-            crt =
-                OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(coec->value.encryptedCert,
-                                                      ctx->libctx, ctx->propq,
-                                                      pkey);
+            crt = OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(coec->value.encryptedCert,
+                                                      ctx->libctx, ctx->propq, pkey, 0);
             break;
         default:
             ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE);
index f59fee44ec26c8c18ed2e053cef6ccf1d7b3180a..fcca08ef4ebf518b3a32a78da3322f17212ec67f 100644 (file)
@@ -130,6 +130,25 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
     }
 }
 
+void ossl_cmp_set_own_chain(OSSL_CMP_CTX *ctx)
+{
+    if (!ossl_assert(ctx != NULL))
+        return;
+    /* if not yet done try to build chain using available untrusted certs */
+    if (ctx->chain == NULL) {
+        ossl_cmp_debug(ctx, "trying to build chain for own CMP signer cert");
+        ctx->chain = X509_build_chain(ctx->cert, ctx->untrusted, NULL, 0,
+                                      ctx->libctx, ctx->propq);
+        if (ctx->chain != NULL) {
+            ossl_cmp_debug(ctx, "success building chain for own CMP signer cert");
+        } else {
+            /* dump errors to avoid confusion when printing further ones */
+            OSSL_CMP_CTX_print_errors(ctx);
+            ossl_cmp_warn(ctx, "could not build chain for own CMP signer cert");
+        }
+    }
+}
+
 /* ctx is not const just because ctx->chain may get adapted */
 int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
 {
@@ -142,22 +161,7 @@ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
         int prepend = X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
             | X509_ADD_FLAG_PREPEND | X509_ADD_FLAG_NO_SS;
 
-        /* if not yet done try to build chain using available untrusted certs */
-        if (ctx->chain == NULL) {
-            ossl_cmp_debug(ctx,
-                           "trying to build chain for own CMP signer cert");
-            ctx->chain = X509_build_chain(ctx->cert, ctx->untrusted, NULL, 0,
-                                          ctx->libctx, ctx->propq);
-            if (ctx->chain != NULL) {
-                ossl_cmp_debug(ctx,
-                               "success building chain for own CMP signer cert");
-            } else {
-                /* dump errors to avoid confusion when printing further ones */
-                OSSL_CMP_CTX_print_errors(ctx);
-                ossl_cmp_warn(ctx,
-                              "could not build chain for own CMP signer cert");
-            }
-        }
+        ossl_cmp_set_own_chain(ctx);
         if (ctx->chain != NULL) {
             if (!ossl_x509_add_certs_new(&msg->extraCerts, ctx->chain, prepend))
                 return 0;
index 791953695576de5b4ad10f93cf45b857dbd7e9e6..d0b35d6f56415d789c2fdb22a79a6085ce50e4a5 100644 (file)
@@ -216,11 +216,12 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
     OSSL_CMP_MSG *msg = NULL;
     OSSL_CMP_PKISI *si = NULL;
     X509 *certOut = NULL;
+    EVP_PKEY *keyOut = NULL;
     STACK_OF(X509) *chainOut = NULL, *caPubs = NULL;
     const OSSL_CRMF_MSG *crm = NULL;
     const X509_REQ *p10cr = NULL;
     int bodytype;
-    int certReqId;
+    int certReqId, central_keygen;
 
     if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
         return NULL;
@@ -263,7 +264,11 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
     }
     srv_ctx->certReqId = certReqId;
 
-    if (!ossl_cmp_verify_popo(srv_ctx->ctx, req, srv_ctx->acceptRAVerified)) {
+    central_keygen = OSSL_CRMF_MSG_centralkeygen_requested(crm, p10cr);
+    if (central_keygen < 0)
+        return NULL;
+    if (central_keygen == 0
+        && !ossl_cmp_verify_popo(srv_ctx->ctx, req, srv_ctx->acceptRAVerified)) {
         /* Proof of possession could not be verified */
         si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
                                      1 << OSSL_CMP_PKIFAILUREINFO_badPOP,
@@ -287,10 +292,13 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
                                          /* do not set if polling starts: */
                                          && certOut != NULL))
             goto err;
+        if (central_keygen == 1
+            && srv_ctx->ctx->newPkey_priv && srv_ctx->ctx->newPkey != NULL)
+            keyOut = srv_ctx->ctx->newPkey;
     }
 
     msg = ossl_cmp_certrep_new(srv_ctx->ctx, bodytype, certReqId, si,
-                               certOut, NULL /* enc */, chainOut, caPubs,
+                               certOut, keyOut, NULL /* enc */, chainOut, caPubs,
                                srv_ctx->sendUnprotectedErrors);
     /* When supporting OSSL_CRMF_POPO_KEYENC, "enc" will need to be set */
     if (msg == NULL)
@@ -299,6 +307,7 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
  err:
     OSSL_CMP_PKISI_free(si);
     X509_free(certOut);
+    OSSL_CMP_CTX_set0_newPkey(srv_ctx->ctx, 0, NULL);
     OSSL_STACK_OF_X509_free(chainOut);
     OSSL_STACK_OF_X509_free(caPubs);
     return msg;
index ecf5a44793b209459edb3192b0b8ead01e9587c4..8b5e018bf5cf2c950c25cc484f35728174be5118 100644 (file)
@@ -243,6 +243,7 @@ ASN1_NDEF_SEQUENCE(CMS_EnvelopedData) = {
         ASN1_SIMPLE(CMS_EnvelopedData, encryptedContentInfo, CMS_EncryptedContentInfo),
         ASN1_IMP_SET_OF_OPT(CMS_EnvelopedData, unprotectedAttrs, X509_ATTRIBUTE, 1)
 } ASN1_NDEF_SEQUENCE_END(CMS_EnvelopedData)
+IMPLEMENT_ASN1_DUP_FUNCTION(CMS_EnvelopedData)
 
 ASN1_NDEF_SEQUENCE(CMS_DigestedData) = {
         ASN1_EMBED(CMS_DigestedData, version, INT32),
index a115a3b9008320a7f078bbe483b03d84fede121b..94289804fc82ce35697e017a55c29c90aeff71e2 100644 (file)
@@ -18,6 +18,7 @@
 #include "internal/cryptlib.h"
 #include "crypto/x509.h"
 #include "cms_local.h"
+#include "internal/cms.h"
 
 static STACK_OF(CMS_CertificateChoices)
 **cms_get0_certificate_choices(CMS_ContentInfo *cms);
@@ -769,3 +770,40 @@ int ossl_cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
     *pkeyid = keyid;
     return 1;
 }
+
+CMS_EnvelopedData *ossl_cms_sign_encrypt(BIO *data, X509 *sign_cert, STACK_OF(X509) *certs,
+                                         EVP_PKEY *sign_key, unsigned int sign_flags,
+                                         STACK_OF(X509) *enc_recip, const EVP_CIPHER *cipher,
+                                         unsigned int enc_flags, OSSL_LIB_CTX *libctx,
+                                         const char *propq)
+{
+    CMS_EnvelopedData *evd = NULL;
+    BIO *privbio = NULL, *signbio = NULL;
+    CMS_ContentInfo *signcms = NULL, *evpcms = NULL;
+
+    if (data == NULL || sign_key == NULL || sign_cert == NULL || enc_recip == NULL) {
+        ERR_raise(ERR_LIB_CMS, ERR_R_PASSED_NULL_PARAMETER);
+        return NULL;
+    }
+    signcms = CMS_sign_ex(sign_cert, sign_key, certs, data, sign_flags, libctx, propq);
+    if (signcms == NULL)
+        goto err;
+
+    signbio = BIO_new(BIO_s_mem());
+    if (signbio == NULL
+        || ASN1_item_i2d_bio(ASN1_ITEM_rptr(CMS_SignedData), signbio, signcms->d.signedData) <= 0)
+        goto err;
+
+    evpcms = CMS_encrypt_ex(enc_recip, signbio, cipher, enc_flags, libctx, propq);
+    if (evpcms == NULL)
+        goto err;
+    evd = CMS_EnvelopedData_dup(evpcms->d.envelopedData);
+
+ err:
+    BIO_free(privbio);
+    BIO_free(signbio);
+    CMS_ContentInfo_free(signcms);
+    CMS_ContentInfo_free(evpcms);
+
+    return evd;
+}
index c3dbc84e78a1c184945e5ff4f49a55622b6ab588..6989484783b53970150fbea5ffc290f4378aea64 100644 (file)
@@ -58,6 +58,21 @@ ASN1_SEQUENCE(OSSL_CRMF_ENCRYPTEDVALUE) = {
 } ASN1_SEQUENCE_END(OSSL_CRMF_ENCRYPTEDVALUE)
 IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE)
 
+/*
+ * Note from CMP Updates defining CMPv3:
+ * The EncryptedKey structure defined in CRMF [RFC4211] is reused
+ * here, which makes the update backward compatible.  Using the new
+ * syntax with the untagged default choice EncryptedValue is bits-on-
+ * the-wire compatible with the old syntax.
+ */
+ASN1_CHOICE(OSSL_CRMF_ENCRYPTEDKEY) = {
+    ASN1_SIMPLE(OSSL_CRMF_ENCRYPTEDKEY, value.encryptedValue, OSSL_CRMF_ENCRYPTEDVALUE),
+#ifndef OPENSSL_NO_CMS
+    ASN1_IMP(OSSL_CRMF_ENCRYPTEDKEY, value.envelopedData, CMS_EnvelopedData, 0),
+#endif
+} ASN1_CHOICE_END(OSSL_CRMF_ENCRYPTEDKEY)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDKEY)
+
 ASN1_SEQUENCE(OSSL_CRMF_SINGLEPUBINFO) = {
     ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubMethod, ASN1_INTEGER),
     ASN1_SIMPLE(OSSL_CRMF_SINGLEPUBINFO, pubLocation, GENERAL_NAME)
index 44b2f2757d2c2614c4042372f32d3380797b8ddd..223ea0f9bf32ab6bb05ee272926090bf3a0432f4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-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
 
 static const ERR_STRING_DATA CRMF_str_reasons[] = {
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_BAD_PBM_ITERATIONCOUNT),
-    "bad pbm iterationcount"},
+     "bad pbm iterationcount"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_CMS_NOT_SUPPORTED), "cms not supported"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_CRMFERROR), "crmferror"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR), "error"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECODING_CERTIFICATE),
-    "error decoding certificate"},
+     "error decoding certificate"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECODING_ENCRYPTEDKEY),
+     "error decoding encryptedkey"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_CERTIFICATE),
-    "error decrypting certificate"},
+     "error decrypting certificate"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY),
+     "error decrypting encryptedkey"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE),
+     "error decrypting encryptedvalue"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY),
-    "error decrypting symmetric key"},
+     "error decrypting symmetric key"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_SETTING_PURPOSE),
+     "error setting purpose"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY),
+     "error verifying encryptedkey"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_FAILURE_OBTAINING_RANDOM),
-    "failure obtaining random"},
+     "failure obtaining random"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_ITERATIONCOUNT_BELOW_100),
-    "iterationcount below 100"},
+     "iterationcount below 100"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_MALFORMED_IV), "malformed iv"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_NULL_ARGUMENT), "null argument"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPOSKINPUT_NOT_SUPPORTED),
-    "poposkinput not supported"},
+     "poposkinput not supported"},
+    {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN),
+     "popo inconsistent central keygen"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY),
-    "popo inconsistent public key"},
+     "popo inconsistent public key"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING), "popo missing"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_PUBLIC_KEY),
-    "popo missing public key"},
+     "popo missing public key"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_SUBJECT),
-    "popo missing subject"},
+     "popo missing subject"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED),
-    "popo raverified not accepted"},
+     "popo raverified not accepted"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_MAC_ALGOR_FAILURE),
-    "setting mac algor failure"},
+     "setting mac algor failure"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_OWF_ALGOR_FAILURE),
-    "setting owf algor failure"},
+     "setting owf algor failure"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_ALGORITHM),
-    "unsupported algorithm"},
+     "unsupported algorithm"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_CIPHER),
-    "unsupported cipher"},
+     "unsupported cipher"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO),
-    "unsupported method for creating popo"},
+     "unsupported method for creating popo"},
     {ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_METHOD),
-    "unsupported popo method"},
+     "unsupported popo method"},
     {0, NULL}
 };
 
index cb077e41d2c4c54f2499aeabc67d1493e4309510..d66929696d80a0945f1576f017e201ae5baf8591 100644 (file)
@@ -29,6 +29,7 @@
 #include <openssl/asn1t.h>
 
 #include "crmf_local.h"
+#include "internal/constant_time.h"
 #include "internal/sizes.h"
 #include "crypto/evp.h"
 #include "crypto/x509.h"
@@ -37,6 +38,7 @@
 #include <openssl/crmf.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
+#include <openssl/cms.h>
 
 /*-
  * atyp = Attribute Type
@@ -542,6 +544,38 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
     return 1;
 }
 
+int OSSL_CRMF_MSG_centralkeygen_requested(const OSSL_CRMF_MSG *crm, const X509_REQ *p10cr)
+{
+    X509_PUBKEY *pubkey = NULL;
+    const unsigned char *pk = NULL;
+    int pklen, ret = 0;
+
+    if (crm == NULL && p10cr == NULL) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+        return -1;
+    }
+
+    if (crm != NULL)
+        pubkey = OSSL_CRMF_CERTTEMPLATE_get0_publicKey(OSSL_CRMF_MSG_get0_tmpl(crm));
+    else
+        pubkey = p10cr->req_info.pubkey;
+
+    if (pubkey == NULL
+        || (X509_PUBKEY_get0_param(NULL, &pk, &pklen, NULL, pubkey)
+            && pklen == 0))
+        ret = 1;
+
+    /*
+     * In case of CRMF, POPO MUST be absent if central key generation
+     * is requested, otherwise MUST be present
+     */
+    if (crm != NULL && ret != (crm->popo == NULL)) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN);
+        return -2;
+    }
+    return ret;
+}
+
 X509_PUBKEY
 *OSSL_CRMF_CERTTEMPLATE_get0_publicKey(const OSSL_CRMF_CERTTEMPLATE *tmpl)
 {
@@ -612,46 +646,155 @@ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
     return 1;
 }
 
-/*-
- * Decrypts the certificate in the given encryptedValue using private key pkey.
- * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2.
- *
- * returns a pointer to the decrypted certificate
- * returns NULL on error or if no certificate available
- */
-X509
-*OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
-                                       OSSL_LIB_CTX *libctx, const char *propq,
-                                       EVP_PKEY *pkey)
+#ifndef OPENSSL_NO_CMS
+DECLARE_ASN1_ITEM(CMS_SignedData) /* copied from cms_local.h */
+
+/* check for KGA authorization implied by CA flag or by explicit EKU cmKGA */
+static int check_cmKGA(ossl_unused const X509_PURPOSE *purpose, const X509 *x, int ca)
+{
+    STACK_OF(ASN1_OBJECT) *ekus;
+    int i, ret = 1;
+
+    if (ca)
+        return ret;
+    ekus = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL);
+    for (i = 0; i < sk_ASN1_OBJECT_num(ekus); i++) {
+        if (OBJ_obj2nid(sk_ASN1_OBJECT_value(ekus, i)) == NID_cmKGA)
+            goto end;
+    }
+    ret = 0;
+
+ end:
+    sk_ASN1_OBJECT_pop_free(ekus, ASN1_OBJECT_free);
+    return ret;
+}
+#endif /* OPENSSL_NO_CMS */
+
+EVP_PKEY *OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(const OSSL_CRMF_ENCRYPTEDKEY *encryptedKey,
+                                           X509_STORE *ts, STACK_OF(X509) *extra, EVP_PKEY *pkey,
+                                           X509 *cert, ASN1_OCTET_STRING *secret,
+                                           OSSL_LIB_CTX *libctx, const char *propq)
+{
+#ifndef OPENSSL_NO_CMS
+    BIO *bio = NULL;
+    CMS_SignedData *sd = NULL;
+    BIO *pkey_bio = NULL;
+    int purpose_id, bak_purpose_id;
+    X509_VERIFY_PARAM *vpm;
+#endif
+    EVP_PKEY *ret = NULL;
+
+    if (encryptedKey == NULL) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+        return NULL;
+    }
+    if (encryptedKey->type != OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA) {
+        unsigned char *p;
+        const unsigned char *p_copy;
+        int len;
+
+        p = OSSL_CRMF_ENCRYPTEDVALUE_decrypt(encryptedKey->value.encryptedValue,
+                                             libctx, propq, pkey, &len);
+        if ((p_copy = p) != NULL)
+            ret = d2i_AutoPrivateKey_ex(NULL, &p_copy, len, libctx, propq);
+        OPENSSL_free(p);
+        return ret;
+    }
+
+#ifndef OPENSSL_NO_CMS
+    if (ts == NULL) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+        return NULL;
+    }
+    if ((bio = CMS_EnvelopedData_decrypt(encryptedKey->value.envelopedData,
+                                         NULL, pkey, cert, secret, 0,
+                                         libctx, propq)) == NULL) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY);
+        goto end;
+    }
+    sd = ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_SignedData), bio, NULL);
+    if (sd == NULL)
+        goto end;
+
+    if ((purpose_id = X509_PURPOSE_get_by_sname(SN_cmKGA)) < 0) {
+        purpose_id = X509_PURPOSE_get_unused_id(libctx);
+        if (!X509_PURPOSE_add(purpose_id, X509_TRUST_COMPAT, 0, check_cmKGA,
+                              LN_cmKGA, SN_cmKGA, NULL))
+            goto end;
+    }
+    if ((vpm = X509_STORE_get0_param(ts)) == NULL)
+        goto end;
+
+    /* temporarily override X509_PURPOSE_SMIME_SIGN: */
+    bak_purpose_id = X509_VERIFY_PARAM_get_purpose(vpm);
+    if (!X509_STORE_set_purpose(ts, purpose_id)) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_SETTING_PURPOSE);
+        goto end;
+    }
+
+    pkey_bio = CMS_SignedData_verify(sd, NULL, NULL /* scerts */, ts,
+                                     extra, NULL, 0, libctx, propq);
+
+    if (!X509_STORE_set_purpose(ts, bak_purpose_id)) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_SETTING_PURPOSE);
+        goto end;
+    }
+
+    if (pkey_bio == NULL) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY);
+        goto end;
+    }
+
+    /* unpack AsymmetricKeyPackage */
+    if ((ret = d2i_PrivateKey_ex_bio(pkey_bio, NULL, libctx, propq)) == NULL)
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_ENCRYPTEDKEY);
+
+ end:
+    CMS_SignedData_free(sd);
+    BIO_free(bio);
+    BIO_free(pkey_bio);
+    return ret;
+#else
+    /* prevent warning on unused parameters: */
+    ((void)ts, (void)extra, (void)cert, (void)secret);
+    ERR_raise(ERR_LIB_CRMF, CRMF_R_CMS_NOT_SUPPORTED);
+    return NULL;
+#endif /* OPENSSL_NO_CMS */
+}
+
+unsigned char
+*OSSL_CRMF_ENCRYPTEDVALUE_decrypt(const OSSL_CRMF_ENCRYPTEDVALUE *enc,
+                                  OSSL_LIB_CTX *libctx, const char *propq,
+                                  EVP_PKEY *pkey, int *outlen)
 {
-    X509 *cert = NULL; /* decrypted certificate */
     EVP_CIPHER_CTX *evp_ctx = NULL; /* context for symmetric encryption */
     unsigned char *ek = NULL; /* decrypted symmetric encryption key */
     size_t eksize = 0; /* size of decrypted symmetric encryption key */
     EVP_CIPHER *cipher = NULL; /* used cipher */
     int cikeysize = 0; /* key size from cipher */
     unsigned char *iv = NULL; /* initial vector for symmetric encryption */
-    unsigned char *outbuf = NULL; /* decryption output buffer */
-    const unsigned char *p = NULL; /* needed for decoding ASN1 */
-    int n, outlen = 0;
+    unsigned char *out = NULL; /* decryption output buffer */
+    int n, ret = 0;
     EVP_PKEY_CTX *pkctx = NULL; /* private key context */
     char name[OSSL_MAX_NAME_SIZE];
 
-    if (ecert == NULL || ecert->symmAlg == NULL || ecert->encSymmKey == NULL
-            || ecert->encValue == NULL || pkey == NULL) {
+    if (outlen == NULL) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
+        return NULL;
+    }
+    *outlen = 0;
+    if (enc == NULL || enc->symmAlg == NULL || enc->encSymmKey == NULL
+            || enc->encValue == NULL || pkey == NULL) {
         ERR_raise(ERR_LIB_CRMF, CRMF_R_NULL_ARGUMENT);
         return NULL;
     }
 
     /* select symmetric cipher based on algorithm given in message */
-    OBJ_obj2txt(name, sizeof(name), ecert->symmAlg->algorithm, 0);
-
+    OBJ_obj2txt(name, sizeof(name), enc->symmAlg->algorithm, 0);
     (void)ERR_set_mark();
-    cipher = EVP_CIPHER_fetch(NULL, name, NULL);
-
+    cipher = EVP_CIPHER_fetch(libctx, name, propq);
     if (cipher == NULL)
-        cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name);
-
+        cipher = (EVP_CIPHER *)EVP_get_cipherbyobj(enc->symmAlg->algorithm);
     if (cipher == NULL) {
         (void)ERR_clear_last_mark();
         ERR_raise(ERR_LIB_CRMF, CRMF_R_UNSUPPORTED_CIPHER);
@@ -662,52 +805,141 @@ X509
     cikeysize = EVP_CIPHER_get_key_length(cipher);
     /* first the symmetric key needs to be decrypted */
     pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
-    if (pkctx == NULL || EVP_PKEY_decrypt_init(pkctx) <= 0
-        || evp_pkey_decrypt_alloc(pkctx, &ek, &eksize, (size_t)cikeysize,
-                                  ecert->encSymmKey->data,
-                                  ecert->encSymmKey->length) <= 0)
+    if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx) > 0) {
+        ASN1_BIT_STRING *encKey = enc->encSymmKey;
+        size_t failure;
+        int retval;
+
+        if (EVP_PKEY_decrypt(pkctx, NULL, &eksize,
+                             encKey->data, encKey->length) <= 0
+                || (ek = OPENSSL_malloc(eksize)) == NULL)
+            goto end;
+        retval = EVP_PKEY_decrypt(pkctx, ek, &eksize, encKey->data, encKey->length);
+        failure = ~constant_time_is_zero_s(constant_time_msb(retval)
+                                           | constant_time_is_zero(retval));
+        failure |= ~constant_time_eq_s(eksize, (size_t)cikeysize);
+        if (failure) {
+            ERR_clear_error(); /* error state may have sensitive information */
+            ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY);
+            goto end;
+        }
+    } else {
         goto end;
-
+    }
     if ((iv = OPENSSL_malloc(EVP_CIPHER_get_iv_length(cipher))) == NULL)
         goto end;
-    if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv,
+    if (ASN1_TYPE_get_octetstring(enc->symmAlg->parameter, iv,
                                   EVP_CIPHER_get_iv_length(cipher))
         != EVP_CIPHER_get_iv_length(cipher)) {
         ERR_raise(ERR_LIB_CRMF, CRMF_R_MALFORMED_IV);
         goto end;
     }
 
-    /*
-     * d2i_X509 changes the given pointer, so use p for decoding the message and
-     * keep the original pointer in outbuf so the memory can be freed later
-     */
-    if ((p = outbuf = OPENSSL_malloc(ecert->encValue->length +
-                                     EVP_CIPHER_get_block_size(cipher))) == NULL
+    if ((out = OPENSSL_malloc(enc->encValue->length +
+                              EVP_CIPHER_get_block_size(cipher))) == NULL
             || (evp_ctx = EVP_CIPHER_CTX_new()) == NULL)
         goto end;
     EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
 
     if (!EVP_DecryptInit(evp_ctx, cipher, ek, iv)
-            || !EVP_DecryptUpdate(evp_ctx, outbuf, &outlen,
-                                  ecert->encValue->data,
-                                  ecert->encValue->length)
-            || !EVP_DecryptFinal(evp_ctx, outbuf + outlen, &n)) {
-        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_CERTIFICATE);
+            || !EVP_DecryptUpdate(evp_ctx, outoutlen,
+                                  enc->encValue->data,
+                                  enc->encValue->length)
+            || !EVP_DecryptFinal(evp_ctx, out + *outlen, &n)) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE);
         goto end;
     }
-    outlen += n;
+    *outlen += n;
+    ret = 1;
 
-    /* convert decrypted certificate from DER to internal ASN.1 structure */
-    if ((cert = X509_new_ex(libctx, propq)) == NULL)
-        goto end;
-    if (d2i_X509(&cert, &p, outlen) == NULL)
-        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE);
  end:
     EVP_PKEY_CTX_free(pkctx);
-    OPENSSL_free(outbuf);
     EVP_CIPHER_CTX_free(evp_ctx);
     EVP_CIPHER_free(cipher);
     OPENSSL_clear_free(ek, eksize);
     OPENSSL_free(iv);
+    if (ret)
+        return out;
+    OPENSSL_free(out);
+    return NULL;
+}
+
+/*
+ * Decrypts the certificate in the given encryptedValue using private key pkey.
+ * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2.
+ *
+ * returns a pointer to the decrypted certificate
+ * returns NULL on error or if no certificate available
+ */
+X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+                                            OSSL_LIB_CTX *libctx, const char *propq,
+                                            EVP_PKEY *pkey)
+{
+    unsigned char *buf = NULL;
+    const unsigned char *p;
+    int len;
+    X509 *cert = NULL;
+
+    buf = OSSL_CRMF_ENCRYPTEDVALUE_decrypt(ecert, libctx, propq, pkey, &len);
+    if ((p = buf) == NULL || (cert = X509_new_ex(libctx, propq)) == NULL)
+        goto end;
+
+    if (d2i_X509(&cert, &p, len) == NULL) {
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE);
+        X509_free(cert);
+        cert = NULL;
+    }
+
+ end:
+    OPENSSL_free(buf);
     return cert;
 }
+/*-
+ * Decrypts the certificate in the given encryptedKey using private key pkey.
+ * This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2.
+ *
+ * returns a pointer to the decrypted certificate
+ * returns NULL on error or if no certificate available
+ */
+X509 *OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(const OSSL_CRMF_ENCRYPTEDKEY *ecert,
+                                          OSSL_LIB_CTX *libctx, const char *propq,
+                                          EVP_PKEY *pkey, unsigned int flags)
+{
+#ifndef OPENSSL_NO_CMS
+    BIO *bio;
+    X509 *cert = NULL;
+#endif
+
+    if (ecert->type != OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA)
+        return OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(ecert->value.encryptedValue,
+                                                     libctx, propq, pkey);
+#ifndef OPENSSL_NO_CMS
+    bio = CMS_EnvelopedData_decrypt(ecert->value.envelopedData, NULL,
+                                    pkey, NULL /* cert */, NULL, flags,
+                                    libctx, propq);
+    if (bio == NULL)
+        return NULL;
+    cert = d2i_X509_bio(bio, NULL);
+    if (cert == NULL)
+        ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECODING_CERTIFICATE);
+    BIO_free(bio);
+    return cert;
+#else
+    (void)flags; /* prevent warning on unused parameter */
+    ERR_raise(ERR_LIB_CRMF, CRMF_R_CMS_NOT_SUPPORTED);
+    return NULL;
+#endif /* OPENSSL_NO_CMS */
+}
+
+#ifndef OPENSSL_NO_CMS
+OSSL_CRMF_ENCRYPTEDKEY *OSSL_CRMF_ENCRYPTEDKEY_init_envdata(CMS_EnvelopedData *envdata)
+{
+    OSSL_CRMF_ENCRYPTEDKEY *ek = OSSL_CRMF_ENCRYPTEDKEY_new();
+
+    if (ek == NULL)
+        return NULL;
+    ek->type = OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA;
+    ek->value.envelopedData = envdata;
+    return ek;
+}
+#endif
index 0b1b7964aa2bad1d280d2d22b914ab16792c4460..b2fa11d5289723021a79f637f7db147cd4c764d7 100644 (file)
@@ -15,6 +15,7 @@
 # define OSSL_CRYPTO_CRMF_LOCAL_H
 
 # include <openssl/crmf.h>
+# include <openssl/cms.h> /* for CMS_EnvelopedData and CMS_SignedData */
 # include <openssl/err.h>
 # include "internal/crmf.h" /* for ossl_crmf_attributetypeandvalue_st */
 
@@ -52,6 +53,25 @@ struct ossl_crmf_encryptedvalue_st {
     ASN1_BIT_STRING *encValue;
 } /* OSSL_CRMF_ENCRYPTEDVALUE */;
 
+/*
+ *    EncryptedKey ::= CHOICE {
+ *       encryptedValue        EncryptedValue, -- Deprecated
+ *       envelopedData     [0] EnvelopedData }
+ *       -- The encrypted private key MUST be placed in the envelopedData
+ *       -- encryptedContentInfo encryptedContent OCTET STRING.
+ */
+# define OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA 1
+
+struct ossl_crmf_encryptedkey_st {
+    int type;
+    union {
+        OSSL_CRMF_ENCRYPTEDVALUE *encryptedValue; /* 0 */ /* Deprecated */
+# ifndef OPENSSL_NO_CMS
+        CMS_EnvelopedData *envelopedData; /* 1 */
+# endif
+    } value;
+} /* OSSL_CRMF_ENCRYPTEDKEY */;
+
 /*-
  *  Attributes ::= SET OF Attribute
  *  => X509_ATTRIBUTE
index e2ce4faede25c64bb147565abeca39adb4bedede..56554f5233714d2273e53752fb507fd57408618c 100644 (file)
@@ -231,6 +231,7 @@ CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
 CMP_R_ERROR_VALIDATING_SIGNATURE:171:error validating signature
 CMP_R_EXPECTED_POLLREQ:104:expected pollreq
 CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain
+CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY:203:failed extracting central gen key
 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
@@ -243,6 +244,7 @@ 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_CENTRAL_GEN_KEY:204:missing central gen key
 CMP_R_MISSING_CERTID:165:missing certid
 CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION:130:\
        missing key input for creating protection
@@ -279,6 +281,7 @@ CMP_R_TOTAL_TIMEOUT:184:total timeout
 CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
 CMP_R_TRANSFER_ERROR:159:transfer error
 CMP_R_UNCLEAN_CTX:191:unclean ctx
+CMP_R_UNEXPECTED_CENTRAL_GEN_KEY:205:unexpected central gen key
 CMP_R_UNEXPECTED_CERTPROFILE:196:unexpected certprofile
 CMP_R_UNEXPECTED_CRLSTATUSLIST:201:unexpected crlstatuslist
 CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
@@ -448,16 +451,23 @@ CONF_R_UNKNOWN_MODULE_NAME:113:unknown module name
 CONF_R_VARIABLE_EXPANSION_TOO_LONG:116:variable expansion too long
 CONF_R_VARIABLE_HAS_NO_VALUE:104:variable has no value
 CRMF_R_BAD_PBM_ITERATIONCOUNT:100:bad pbm iterationcount
+CRMF_R_CMS_NOT_SUPPORTED:122:cms not supported
 CRMF_R_CRMFERROR:102:crmferror
 CRMF_R_ERROR:103:error
 CRMF_R_ERROR_DECODING_CERTIFICATE:104:error decoding certificate
+CRMF_R_ERROR_DECODING_ENCRYPTEDKEY:123:error decoding encryptedkey
 CRMF_R_ERROR_DECRYPTING_CERTIFICATE:105:error decrypting certificate
+CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY:124:error decrypting encryptedkey
+CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE:125:error decrypting encryptedvalue
 CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY:106:error decrypting symmetric key
+CRMF_R_ERROR_SETTING_PURPOSE:126:error setting purpose
+CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY:127:error verifying encryptedkey
 CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random
 CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100
 CRMF_R_MALFORMED_IV:101:malformed iv
 CRMF_R_NULL_ARGUMENT:109:null argument
 CRMF_R_POPOSKINPUT_NOT_SUPPORTED:113:poposkinput not supported
+CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN:128:popo inconsistent central keygen
 CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY:117:popo inconsistent public key
 CRMF_R_POPO_MISSING:121:popo missing
 CRMF_R_POPO_MISSING_PUBLIC_KEY:118:popo missing public key
diff --git a/doc/internal/man3/ossl_cms_sign_encrypt.pod b/doc/internal/man3/ossl_cms_sign_encrypt.pod
new file mode 100644 (file)
index 0000000..ee77e76
--- /dev/null
@@ -0,0 +1,56 @@
+=pod
+
+=head1 NAME
+
+ossl_cms_sign_encrypt
+- Create CMS envelope
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ CMS_EnvelopedData *ossl_cms_sign_encrypt(BIO *data, X509 *sign_cert, STACK_OF(X509) *certs,
+                                          EVP_PKEY *sign_key, unsigned int sign_flags,
+                                          STACK_OF(X509) *enc_recip, const EVP_CIPHER *cipher,
+                                          unsigned int enc_flags, OSSL_LIB_CTX *libctx,
+                                          const char *propq);
+
+=head1 DESCRIPTION
+
+ossl_cms_sign_encrypt() creates a B<CMS_EnvelopedData> structure for recipients in
+I<enc_recip>.
+
+I<data> is signed using I<signcert> and I<signkey> to create B<CMS_SignedData> 
+and then encrypted using I<enc_recip> to create B<CMS_EnvelopedData>.
+The library context I<libctx> and the property query I<propq> are used
+when retrieving algorithms from providers.
+
+I<certs> is an optional additional set of certificates to include in the
+B<CMS_SignedData> structure (e.g., any intermediate CAs in the chain of the signer certificate).
+
+I<sign_flags> is an optional set of flags for the signing operation.
+See L<CMS_sign_ex(3)> for more information.
+
+I<enc_flags> is an optional set of flags for the encryption operation.
+See L<CMS_encrypt_ex(3)> for more information.
+
+=head1 RETURN VALUES
+
+If the allocation fails, ossl_cms_sign_encrypt() returns NULL and
+sets an error code that can be obtained by L<ERR_get_error(3)>.
+Otherwise, it returns a pointer to the newly allocated structure.
+
+=head1 HISTORY
+
+ossl_cms_sign_encrypt() was added in OpenSSL 3.5.
+
+=head1 COPYRIGHT
+
+Copyright 2023 - 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 a5a8167dd65e54060b9e5e98cdaa64e8f1e9190a..5fd0cb6915f78816f0f0e7d56ef2105065d4aec2 100644 (file)
@@ -26,6 +26,8 @@ Certificate enrollment options:
 
 [B<-newkey> I<filename>|I<uri>]
 [B<-newkeypass> I<arg>]
+[B<-centralkeygen>
+[B<-newkeyout> I<filename>]
 [B<-subject> I<name>]
 [B<-days> I<number>]
 [B<-reqexts> I<name>]
@@ -140,6 +142,8 @@ 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_key> I<filename>|I<uri>]
+[B<-rsp_keypass> 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>]
@@ -308,6 +312,15 @@ If not given here, the password will be prompted for if needed.
 For more information about the format of I<arg> see
 L<openssl-passphrase-options(1)>.
 
+=item B<-centralkeygen>
+
+Request central key generation for certificate enrollment.
+This applies to B<-cmd> I<ir|cr|kur|p10cr>.
+
+=item B<-newkeyout> I<filename>
+
+File to save centrally generated private key, in PEM format.
+
 =item B<-subject> I<name>
 
 X.509 Distinguished Name (DN) to use as subject field
@@ -380,7 +393,8 @@ Flag the policies given with B<-policy_oids> as critical.
 =item B<-popo> I<number>
 
 Proof-of-possession (POPO) method to use for IR/CR/KUR; values: C<-1>..<2> where
-C<-1> = NONE, C<0> = RAVERIFIED, C<1> = SIGNATURE (default), C<2> = KEYENC.
+C<-1> = NONE, which implies central key generation,
+C<0> = RAVERIFIED, C<1> = SIGNATURE (default), C<2> = KEYENC.
 
 Note that a signature-based POPO can only be produced if a private key
 is provided via the B<-newkey> or B<-key> options.
@@ -920,7 +934,7 @@ See L<openssl(1)/Format Options> for details.
 
 Pass phrase source for certificate given with the B<-trusted>, B<-untrusted>,
 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<-srv_trusted>, B<-srv_untrusted>, B<-ref_cert>,
 B<-rsp_extracerts>, B<-rsp_capubs>,
 B<-rsp_newwithnew>, B<-rsp_newwithold>, B<-rsp_oldwithnew>,
 B<-tls_extra>, and B<-tls_trusted> options.
@@ -1194,6 +1208,14 @@ Certificate to be expected for RR messages and any oldCertID in KUR messages.
 
 Certificate to be returned as mock enrollment result.
 
+=item B<-rsp_key> I<filename>|I<uri>
+
+Private key to be returned as central key generation result.
+
+=item B<-rsp_keypass> I<arg>
+
+Pass phrase source for B<rsp_cert> and B<rsp_key>.
+
 =item B<-rsp_crl> I<filename>|I<uri>
 
 CRL to be returned in genp of type C<crls>.
@@ -1500,6 +1522,9 @@ The B<-profile> option was added in OpenSSL 3.3.
 B<-crlcert>, B<-oldcrl>, B<-crlout>, B<-crlform>
 and B<-rsp_crl> options were added in OpenSSL 3.4.
 
+B<-centralkeygen>, b<-newkeyout>, B<-rsp_key> and
+B<-rsp_keypass> were added in OpenSSL 3.5.
+
 =head1 COPYRIGHT
 
 Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
index 9dfd0ad77d8c075d7d04ad7b6edd7eedac3103f5..c02b764842912a0e30085cfe5c552eec7018c8dd 100644 (file)
@@ -57,19 +57,24 @@ The wrappers L<CMS_encrypt(3)> and L<CMS_decrypt(3)> are often used instead.
 =head1 RETURN VALUES
 
 If the allocation fails, CMS_EnvelopedData_create_ex(),
-CMS_EnvelopedData_create(), CMS_AuthEnvelopedData_create_ex(), and
-CMS_AuthEnvelopedData_create() return NULL and set an error code that can be
-obtained by L<ERR_get_error(3)>. Otherwise they return a pointer to the newly
-allocated structure.
+CMS_EnvelopedData_create(), CMS_AuthEnvelopedData_create_ex(),
+CMS_AuthEnvelopedData_create(), CMS_AuthEnvelopedData_create(),
+and CMS_AuthEnvelopedData_create_ex() return NULL and set an
+error code that can be obtained by L<ERR_get_error(3)>.
+Otherwise, they return a pointer to the newly allocated structure.
 
 =head1 SEE ALSO
 
-L<ERR_get_error(3)>, L<CMS_encrypt(3)>, L<CMS_decrypt(3)>, L<CMS_final(3)>
+L<ERR_get_error(3)>, L<CMS_encrypt(3)>, L<CMS_decrypt(3)>, L<CMS_final(3)>,
+L<CMS_sign_ex(3)>, L<CMS_encrypt_ex(3)>
 
 =head1 HISTORY
 
 The CMS_EnvelopedData_create_ex() method was added in OpenSSL 3.0.
 
+CMS_AuthEnvelopedData_create() and CMS_AuthEnvelopedData_create_ex()
+were added in OpenSSL 3.5.
+
 =head1 COPYRIGHT
 
 Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
index 01474ee0ba1ccf68e9bf3d6ad009949bec1dba76..483524981a5c1d3de5c7841be6d7f989366ba6df 100644 (file)
@@ -273,7 +273,8 @@ The following options can be set:
 
         Select the proof of possession method to use. Possible values are:
 
-            OSSL_CRMF_POPO_NONE       - ProofOfPossession field omitted
+            OSSL_CRMF_POPO_NONE       - ProofOfPossession field omitted,
+                                        which implies central key generation
             OSSL_CRMF_POPO_RAVERIFIED - assert that the RA has already
                                         verified the PoPo
             OSSL_CRMF_POPO_SIGNATURE  - sign a value with private key,
index 749a1719c9178257a216041598854fa846867b90..cffd633616c3a4b7b6394fd2d466dfe84ca1d08c 100644 (file)
@@ -10,8 +10,13 @@ OSSL_CRMF_CERTTEMPLATE_get0_serialNumber,
 OSSL_CRMF_CERTTEMPLATE_get0_extensions,
 OSSL_CRMF_CERTID_get0_serialNumber,
 OSSL_CRMF_CERTID_get0_issuer,
+OSSL_CRMF_ENCRYPTEDKEY_get1_encCert,
+OSSL_CRMF_ENCRYPTEDKEY_get1_pkey,
+OSSL_CRMF_ENCRYPTEDKEY_init_envdata,
+OSSL_CRMF_ENCRYPTEDVALUE_decrypt,
 OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert,
-OSSL_CRMF_MSG_get_certReqId
+OSSL_CRMF_MSG_get_certReqId,
+OSSL_CRMF_MSG_centralkeygen_requested
 - functions reading from CRMF CertReqMsg structures
 
 =head1 SYNOPSIS
@@ -34,12 +39,30 @@ OSSL_CRMF_MSG_get_certReqId
  *OSSL_CRMF_CERTID_get0_serialNumber(const OSSL_CRMF_CERTID *cid);
  const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid);
 
+ X509 *OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(const OSSL_CRMF_ENCRYPTEDKEY *ecert,
+                                           OSSL_LIB_CTX *libctx, const char *propq,
+                                           EVP_PKEY *pkey, unsigned int flags);
+ EVP_PKEY
+ *OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(OSSL_CRMF_ENCRYPTEDKEY *encryptedKey,
+                                   X509_STORE *ts, STACK_OF(X509) *extra,
+                                   EVP_PKEY *pkey, X509 *cert,
+                                   ASN1_OCTET_STRING *secret,
+                                   OSSL_LIB_CTX *libctx, const char *propq);
+ OSSL_CRMF_ENCRYPTEDKEY
+ *OSSL_CRMF_ENCRYPTEDKEY_init_envdata(CMS_EnvelopedData *envdata);
+
+ unsigned char
+ *OSSL_CRMF_ENCRYPTEDVALUE_decrypt(const OSSL_CRMF_ENCRYPTEDVALUE *enc,
+                                   OSSL_LIB_CTX *libctx, const char *propq,
+                                   EVP_PKEY *pkey, int *outlen);
  X509
  *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
                                         OSSL_LIB_CTX *libctx, const char *propq,
                                         EVP_PKEY *pkey);
 
  int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm);
+ int OSSL_CRMF_MSG_centralkeygen_requested(const OSSL_CRMF_MSG *crm,
+                                           const X509_REQ *p10cr);
 
 =head1 DESCRIPTION
 
@@ -66,6 +89,33 @@ of the given CertId I<cid>.
 OSSL_CRMF_CERTID_get0_issuer retrieves the issuer name
 of the given CertId I<cid>, which must be of ASN.1 type GEN_DIRNAME.
 
+OSSL_CRMF_ENCRYPTEDKEY_get1_encCert() decrypts the certificate in the given
+encryptedKey I<ecert>, using the private key I<pkey>, library context
+I<libctx> and property query string I<propq> (see L<OSSL_LIB_CTX(3)>).
+This is needed for the indirect POPO method as in RFC 4210 section 5.2.8.2.
+The function returns the decrypted certificate as a copy, leaving its ownership
+with the caller, who is responsible for freeing it.
+
+OSSL_CRMF_ENCRYPTEDKEY_get1_pkey() decrypts the private key in I<encryptedKey>.
+If I<encryptedKey> is not of type B<OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA>,
+decryption uses the private key I<pkey>.
+The library context I<libctx> and property query I<propq> are taken into account as usual.
+The rest of this paragraph is relevant only if CMS support not disabled for the OpenSSL build
+and I<encryptedKey> is of type case B<OSSL_CRMF_ENCRYPTEDKEY_ENVELOPEDDATA>.
+Decryption uses the I<secret> parameter if not NULL;
+otherwise uses the private key <pkey> and the certificate I<cert> 
+related to I<pkey>, where I<cert> is recommended to be given if available.
+On success, the function verifies the decrypted data as signed data,
+using the trust store I<ts> and any untrusted certificates in I<extra>.
+Doing so, it checks for the purpose "CMP Key Generation Authority" (cmKGA).
+
+OSSL_CRMF_ENCRYPTEDKEY_init_envdata() returns I<OSSL_CRMF_ENCRYPTEDKEY>, intialized with 
+the enveloped data I<envdata>.
+
+OSSL_CRMF_ENCRYPTEDVALUE_decrypt() decrypts the encrypted value in the given
+encryptedValue I<enc>, using the private key I<pkey>, library context
+I<libctx> and property query string I<propq> (see L<OSSL_LIB_CTX(3)>).
+
 OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert() decrypts the certificate in the given
 encryptedValue I<ecert>, using the private key I<pkey>, library context
 I<libctx> and property query string I<propq> (see L<OSSL_LIB_CTX(3)>).
@@ -75,11 +125,21 @@ with the caller, who is responsible for freeing it.
 
 OSSL_CRMF_MSG_get_certReqId() retrieves the certReqId of I<crm>.
 
+OSSL_CRMF_MSG_centralkeygen_requested() returns 1 if central key generation
+is requested i.e., the public key in the certificate request (I<crm> is taken if it is non-NULL,
+otherwise I<p10cr>) is NULL or has an empty key value (with length zero).
+In case I<crm> is non-NULL, this is checked for consistency with its B<popo> field
+(must be NULL if and only if central key generation is requested).
+Otherwise it returns 0, and on error a negative value.
+
 =head1 RETURN VALUES
 
 OSSL_CRMF_MSG_get_certReqId() returns the certificate request ID as a
 nonnegative integer or -1 on error.
 
+OSSL_CRMF_MSG_centralkeygen_requested() returns 1 if central key generation
+is requested, 0 if it is not requested, and a negative value on error.
+
 All other functions return a pointer with the intended result or NULL on error.
 
 =head1 SEE ALSO
@@ -92,6 +152,10 @@ The OpenSSL CRMF support was added in OpenSSL 3.0.
 
 OSSL_CRMF_CERTTEMPLATE_get0_publicKey() was added in OpenSSL 3.2.
 
+OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(), OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(),
+OSSL_CRMF_ENCRYPTEDKEY_init_envdata(), OSSL_CRMF_ENCRYPTEDVALUE_decrypt()
+and OSSL_CRMF_MSG_centralkeygen_requested() were added in OpenSSL 3.5.
+
 =head1 COPYRIGHT
 
 Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
index 221198c86b07e4a7a6ab972af4f0b6b10ec03a99..d35c2e2202e8c6cacbfedebb0e738d87b8b59b6e 100644 (file)
@@ -240,6 +240,9 @@ X509_VERIFY_PARAM_get_depth() returns the current verification depth.
 X509_VERIFY_PARAM_get_auth_level() returns the current authentication security
 level.
 
+X509_VERIFY_PARAM_get_purpose() returns the current purpose,
+which may be B<X509_PURPOSE_DEFAULT_ANY> if unset.
+
 =head1 VERIFICATION FLAGS
 
 The verification flags consists of zero or more of the following flags
index 70acbc3d58fffcd36250ecf7ec709e290185efe0..0fe4876dc41e2ecee13edbbda5639ffd7df04e11 100644 (file)
@@ -64,7 +64,8 @@ keyUsage, extendedKeyUsage, and basicConstraints.
 
 X509_PURPOSE_get_count() returns the number of currently defined purposes.
 
-X509_PURPOSE_get_unused_id() returns the smallest purpose id not yet used.
+X509_PURPOSE_get_unused_id() returns the smallest purpose id not yet used,
+which is guaranteed to be unique and larger than B<X509_PURPOSE_MAX>.
 The I<libctx> parameter should be used to provide the library context.
 It is currently ignored as the purpose mapping table is global.
 
index 60765766227d8edeed95bcb3571c8faffa3266c7..b85c2cbb400778ce8883271fd05c65b7d625f61c 100644 (file)
@@ -32,6 +32,7 @@ CMS_ContentInfo_new,
 CMS_ContentInfo_new_ex,
 CMS_ContentInfo_print_ctx,
 CMS_EnvelopedData_it,
+CMS_EnvelopedData_dup,
 CMS_ReceiptRequest_free,
 CMS_ReceiptRequest_new,
 CMS_SignedData_free,
@@ -202,6 +203,9 @@ OSSL_CRMF_CERTTEMPLATE_new,
 OSSL_CRMF_CERTTEMPLATE_dup,
 OSSL_CRMF_ATTRIBUTETYPEANDVALUE_dup,
 OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free,
+OSSL_CRMF_ENCRYPTEDKEY_free,
+OSSL_CRMF_ENCRYPTEDKEY_it,
+OSSL_CRMF_ENCRYPTEDKEY_new,
 OSSL_CRMF_ENCRYPTEDVALUE_free,
 OSSL_CRMF_ENCRYPTEDVALUE_it,
 OSSL_CRMF_ENCRYPTEDVALUE_new,
@@ -595,7 +599,9 @@ OSSL_TIME_SPEC_TIME_it(), OSSL_TIME_SPEC_TIME_new(),
 OSSL_TIME_SPEC_WEEKS_free(), OSSL_TIME_SPEC_WEEKS_it(),
 OSSL_TIME_SPEC_WEEKS_new(), OSSL_TIME_SPEC_X_DAY_OF_free(),
 OSSL_TIME_SPEC_X_DAY_OF_it(), OSSL_TIME_SPEC_X_DAY_OF_new(),
-OSSL_TIME_SPEC_free(), OSSL_TIME_SPEC_it(), OSSL_TIME_SPEC_new()
+OSSL_TIME_SPEC_free(), OSSL_TIME_SPEC_it(), OSSL_TIME_SPEC_new(),
+CMS_EnvelopedData_dup(), OSSL_CRMF_ENCRYPTEDKEY_free(),
+OSSL_CRMF_ENCRYPTEDKEY_it() and OSSL_CRMF_ENCRYPTEDKEY_new()
 were added in OpenSSL 3.5.
 
 =head1 COPYRIGHT
index e6df4caf680dd858e9ab1749d63c359b7bdb0626..21dacef396045163036bf226fc56746b5ca38820 100644 (file)
@@ -108,6 +108,7 @@ d2i_OSSL_CMP_PKIHEADER,
 d2i_OSSL_CMP_PKISI,
 d2i_OSSL_CRMF_CERTID,
 d2i_OSSL_CRMF_CERTTEMPLATE,
+d2i_OSSL_CRMF_ENCRYPTEDKEY,
 d2i_OSSL_CRMF_ENCRYPTEDVALUE,
 d2i_OSSL_CRMF_MSG,
 d2i_OSSL_CRMF_MSGS,
@@ -322,6 +323,7 @@ i2d_OSSL_CMP_PKIHEADER,
 i2d_OSSL_CMP_PKISI,
 i2d_OSSL_CRMF_CERTID,
 i2d_OSSL_CRMF_CERTTEMPLATE,
+i2d_OSSL_CRMF_ENCRYPTEDKEY,
 i2d_OSSL_CRMF_ENCRYPTEDVALUE,
 i2d_OSSL_CRMF_MSG,
 i2d_OSSL_CRMF_MSGS,
@@ -734,6 +736,7 @@ i2d_OSSL_ATTRIBUTE_VALUE_MAPPING(), i2d_OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX(),
 i2d_OSSL_HASH(), i2d_OSSL_INFO_SYNTAX(),
 i2d_OSSL_INFO_SYNTAX_POINTER(), i2d_OSSL_PRIVILEGE_POLICY_ID(),
 i2d_OSSL_ROLE_SPEC_CERT_ID(), i2d_OSSL_ROLE_SPEC_CERT_ID_SYNTAX(),
+d2i_OSSL_CRMF_ENCRYPTEDKEY(), i2d_OSSL_CRMF_ENCRYPTEDKEY(),
 d2i_OSSL_DAY_TIME(), d2i_OSSL_DAY_TIME_BAND(), d2i_OSSL_NAMED_DAY(),
 d2i_OSSL_TIME_PERIOD(), d2i_OSSL_TIME_SPEC(),
 d2i_OSSL_TIME_SPEC_ABSOLUTE(), d2i_OSSL_TIME_SPEC_DAY(),
diff --git a/include/internal/cms.h b/include/internal/cms.h
new file mode 100644 (file)
index 0000000..59cdae7
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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_INTERNAL_CMS_H
+# define OSSL_INTERNAL_CMS_H
+# pragma once
+
+# include <openssl/cms.h>
+
+# ifndef OPENSSL_NO_CMS
+CMS_EnvelopedData *ossl_cms_sign_encrypt(BIO *data, X509 *sign_cert, STACK_OF(X509) *certs,
+                                         EVP_PKEY *sign_key, unsigned int sign_flags,
+                                         STACK_OF(X509) *enc_recip, const EVP_CIPHER *cipher,
+                                         unsigned int enc_flags, OSSL_LIB_CTX *libctx,
+                                         const char *propq);
+# endif /* OPENSSL_NO_CMS */
+#endif /* OSSL_INTERNAL_CMS_H */
index d196924f74767121ec6c98744f2ed65d8c6a50cc..74fcda665fd834b04d981a34bef33a869ed558d7 100644 (file)
@@ -57,6 +57,7 @@
 #  define CMP_R_ERROR_VALIDATING_SIGNATURE                 171
 #  define CMP_R_EXPECTED_POLLREQ                           104
 #  define CMP_R_FAILED_BUILDING_OWN_CHAIN                  164
+#  define CMP_R_FAILED_EXTRACTING_CENTRAL_GEN_KEY          203
 #  define CMP_R_FAILED_EXTRACTING_PUBKEY                   141
 #  define CMP_R_FAILURE_OBTAINING_RANDOM                   110
 #  define CMP_R_FAIL_INFO_OUT_OF_RANGE                     129
@@ -69,6 +70,7 @@
 #  define CMP_R_INVALID_KEYSPEC                            202
 #  define CMP_R_INVALID_OPTION                             174
 #  define CMP_R_INVALID_ROOTCAKEYUPDATE                    195
+#  define CMP_R_MISSING_CENTRAL_GEN_KEY                    204
 #  define CMP_R_MISSING_CERTID                             165
 #  define CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION  130
 #  define CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE         142
 #  define CMP_R_TRANSACTIONID_UNMATCHED                    152
 #  define CMP_R_TRANSFER_ERROR                             159
 #  define CMP_R_UNCLEAN_CTX                                191
+#  define CMP_R_UNEXPECTED_CENTRAL_GEN_KEY                 205
 #  define CMP_R_UNEXPECTED_CERTPROFILE                     196
 #  define CMP_R_UNEXPECTED_CRLSTATUSLIST                   201
 #  define CMP_R_UNEXPECTED_PKIBODY                         133
index 15e21aa5c50a1b65007c806e3eea395b6ba0b713..ed675868ce6d0d5612fe0c2bb0fc4ce84a13bc93 100644 (file)
@@ -57,6 +57,8 @@ DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
 DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)
 DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
 
+DECLARE_ASN1_DUP_FUNCTION(CMS_EnvelopedData)
+
 CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq);
 
 # define CMS_SIGNERINFO_ISSUER_SERIAL    0
index 17dc4d9103a6eb804d7d961984fb19d72c6cbd62..90dafafae5fb81ee885f6aef3f6c1ac9c4f80b2b 100644 (file)
@@ -27,6 +27,7 @@ use OpenSSL::stackhash qw(generate_stack_macros);
 #  include <openssl/safestack.h>
 #  include <openssl/crmferr.h>
 #  include <openssl/x509v3.h> /* for GENERAL_NAME etc. */
+#  include <openssl/cms.h>
 
 /* explicit #includes not strictly needed since implied by the above: */
 #  include <openssl/types.h>
@@ -45,8 +46,11 @@ extern "C" {
 #  define OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT       0
 #  define OSSL_CRMF_SUBSEQUENTMESSAGE_CHALLENGERESP  1
 typedef struct ossl_crmf_encryptedvalue_st OSSL_CRMF_ENCRYPTEDVALUE;
-
 DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDVALUE)
+
+typedef struct ossl_crmf_encryptedkey_st OSSL_CRMF_ENCRYPTEDKEY;
+DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_ENCRYPTEDKEY)
+
 typedef struct ossl_crmf_msg_st OSSL_CRMF_MSG;
 DECLARE_ASN1_FUNCTIONS(OSSL_CRMF_MSG)
 DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_MSG)
@@ -177,10 +181,24 @@ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
                                 const X509_NAME *subject,
                                 const X509_NAME *issuer,
                                 const ASN1_INTEGER *serial);
-X509
-*OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
-                                       OSSL_LIB_CTX *libctx, const char *propq,
-                                       EVP_PKEY *pkey);
+X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
+                                            OSSL_LIB_CTX *libctx, const char *propq,
+                                            EVP_PKEY *pkey);
+X509 *OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(const OSSL_CRMF_ENCRYPTEDKEY *ecert,
+                                          OSSL_LIB_CTX *libctx, const char *propq,
+                                          EVP_PKEY *pkey, unsigned int flags);
+unsigned char
+*OSSL_CRMF_ENCRYPTEDVALUE_decrypt(const OSSL_CRMF_ENCRYPTEDVALUE *enc,
+                                  OSSL_LIB_CTX *libctx, const char *propq,
+                                  EVP_PKEY *pkey, int *outlen);
+EVP_PKEY *OSSL_CRMF_ENCRYPTEDKEY_get1_pkey(const OSSL_CRMF_ENCRYPTEDKEY *encryptedKey,
+                                           X509_STORE *ts, STACK_OF(X509) *extra, EVP_PKEY *pkey,
+                                           X509 *cert, ASN1_OCTET_STRING *secret,
+                                           OSSL_LIB_CTX *libctx, const char *propq);
+int OSSL_CRMF_MSG_centralkeygen_requested(const OSSL_CRMF_MSG *crm, const X509_REQ *p10cr);
+#  ifndef OPENSSL_NO_CMS
+OSSL_CRMF_ENCRYPTEDKEY *OSSL_CRMF_ENCRYPTEDKEY_init_envdata(CMS_EnvelopedData *envdata);
+#  endif
 
 #  ifdef __cplusplus
 }
index b242b922ef1a72aff3382af3d2670b04c95966f8..d67270a4c1c31dedb301e13b55296d38cb2d8ad2 100644 (file)
  * CRMF reason codes.
  */
 #  define CRMF_R_BAD_PBM_ITERATIONCOUNT                    100
+#  define CRMF_R_CMS_NOT_SUPPORTED                         122
 #  define CRMF_R_CRMFERROR                                 102
 #  define CRMF_R_ERROR                                     103
 #  define CRMF_R_ERROR_DECODING_CERTIFICATE                104
+#  define CRMF_R_ERROR_DECODING_ENCRYPTEDKEY               123
 #  define CRMF_R_ERROR_DECRYPTING_CERTIFICATE              105
+#  define CRMF_R_ERROR_DECRYPTING_ENCRYPTEDKEY             124
+#  define CRMF_R_ERROR_DECRYPTING_ENCRYPTEDVALUE           125
 #  define CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY            106
+#  define CRMF_R_ERROR_SETTING_PURPOSE                     126
+#  define CRMF_R_ERROR_VERIFYING_ENCRYPTEDKEY              127
 #  define CRMF_R_FAILURE_OBTAINING_RANDOM                  107
 #  define CRMF_R_ITERATIONCOUNT_BELOW_100                  108
 #  define CRMF_R_MALFORMED_IV                              101
 #  define CRMF_R_NULL_ARGUMENT                             109
 #  define CRMF_R_POPOSKINPUT_NOT_SUPPORTED                 113
+#  define CRMF_R_POPO_INCONSISTENT_CENTRAL_KEYGEN          128
 #  define CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY              117
 #  define CRMF_R_POPO_MISSING                              121
 #  define CRMF_R_POPO_MISSING_PUBLIC_KEY                   118
index 7b8a5b237b37b2d733c4957cedcda178eb84bb00..3e90001a616940b76444745696c8e8faf9f32e9a 100644 (file)
@@ -32,6 +32,8 @@ plan skip_all => "These tests are not supported in a no-sock build"
     if disabled("sock");
 plan skip_all => "These tests are not supported in a no-http build"
     if disabled("http");
+plan skip_all => "These tests are not supported in a no-cms build"
+    if disabled("cms"); # central key pair generation
 
 plan skip_all => "Tests involving local HTTP server not available on Windows or VMS"
     if $^O =~ /^(VMS|MSWin32|msys)$/;
index 86a11f6a368297495c29df28fa97f4d00c24a238..e2a47ff62edfa07a57165f17ddf3861b30c5fe4d 100644 (file)
@@ -12,6 +12,7 @@ no_cache_extracerts = 1
 
 ref_cert = signer_only.crt
 rsp_cert = signer_only.crt
+rsp_key = new.key
 rsp_crl = newcrl.pem
 rsp_capubs = trusted.crt
 rsp_extracerts = signer_issuing.crt
index 07eab2e63b8e299bcf7f3bacb8f1eae6fb99386b..d49b846995f24008703ce5bedce4454ea075c3bc 100644 (file)
@@ -1,24 +1,25 @@
         Issuer: CN=Root CA
         Validity
-            Not Before: Jan 14 22:29:46 2016 GMT
-            Not After : Jan 15 22:29:46 2116 GMT
+            Not Before: Aug 8 13:28:36 2024 GMT
+            Not After : Apr 11 13:28:36 2127 GMT
         Subject: CN=server.example
 -----BEGIN CERTIFICATE-----
-MIIDJTCCAg2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
-IENBMCAXDTE2MDExNDIyMjk0NloYDzIxMTYwMTE1MjIyOTQ2WjAZMRcwFQYDVQQD
-DA5zZXJ2ZXIuZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-ANVdYGrf/GHuSKqMEUhDpW22Ul2qmEmxYZI1sfw6BCUMbXn/tNXJ6VwcO+Crs7h9
-o95tveDd11q/FEcRQl6mgtBhwX/dE0bmCYUHDvLU/Bpk0gqtIKsga5bwrczEGVNV
-3AEdpLPvirRJU12KBRzx3OFEv8XX4ncZV1yXC3XuiENxD8pswbSyUKd3RmxYDxG/
-8XYkWq45QrdRZynh0FUwbxfkkeqt+CjCQ2+iZKn7nZiSYkg+6w1PgkqK/z9y7pa1
-rqHBmLrvfZB1bf9aUp6r9cB+0IdD24UHBw99OHr90dPuZR3T6jlqhzfuStPgDW71
-cKzCvfFu85KVXqnwoWWVk40CAwEAAaN9MHswHQYDVR0OBBYEFMDnhL/oWSczELBS
-T1FSLwbWwHrNMB8GA1UdIwQYMBaAFHB/Lq6DaFmYBCMqzes+F80k3QFJMAkGA1Ud
-EwQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwGQYDVR0RBBIwEIIOc2VydmVyLmV4
-YW1wbGUwDQYJKoZIhvcNAQELBQADggEBAHvTBEN1ig8RrsT716Ginv4gGNX0LzGI
-RrZ1jO7lm5emuaPNYJpGw0iX5Zdo91qGNXPZaZ75X3S55pQTActq3OPEBOll2pyk
-iyjz+Zp/v5cfRZLlBbFW5gv2R94eibYr4U3fSn4B0yPcl4xH/l/HzJhGDsSDW8qK
-8VIJvmvsPwmL0JMCv+FR59F+NFYZdND/KCXet59WUpF9ICmFCoBEX3EyJXEPwhbi
-X2sdPzJbCjx0HLli8e0HUKNttLQxCsBTRGo6iISLLamwN47mGDa9miBADwGSiz2q
-YeeuLO02zToHhnQ6KbPXOrQAqcL1kngO4g+j/ru+4AZThFkdkGnltvk=
+MIIDVDCCAjygAwIBAgIUMoDahWpYk1B1WIjOwkom4s27V/EwDQYJKoZIhvcNAQEL
+BQAwEjEQMA4GA1UEAwwHUm9vdCBDQTAgFw0yNDA4MDgxMzI4MzZaGA8yMTI3MDQx
+MTEzMjgzNlowGTEXMBUGA1UEAwwOc2VydmVyLmV4YW1wbGUwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDVXWBq3/xh7kiqjBFIQ6VttlJdqphJsWGSNbH8
+OgQlDG15/7TVyelcHDvgq7O4faPebb3g3ddavxRHEUJepoLQYcF/3RNG5gmFBw7y
+1PwaZNIKrSCrIGuW8K3MxBlTVdwBHaSz74q0SVNdigUc8dzhRL/F1+J3GVdclwt1
+7ohDcQ/KbMG0slCnd0ZsWA8Rv/F2JFquOUK3UWcp4dBVMG8X5JHqrfgowkNvomSp
++52YkmJIPusNT4JKiv8/cu6Wta6hwZi6732QdW3/WlKeq/XAftCHQ9uFBwcPfTh6
+/dHT7mUd0+o5aoc37krT4A1u9XCswr3xbvOSlV6p8KFllZONAgMBAAGjgZgwgZUw
+CQYDVR0TBAIwADAdBgNVHQ4EFgQUwOeEv+hZJzMQsFJPUVIvBtbAes0wHwYDVR0j
+BBgwFoAUcH8uroNoWZgEIyrN6z4XzSTdAUkwDgYDVR0PAQH/BAQDAgWgMB0GA1Ud
+JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDIDAZBgNVHREEEjAQgg5zZXJ2ZXIuZXhh
+bXBsZTANBgkqhkiG9w0BAQsFAAOCAQEAPRQ87zMFGrcQau8h8wDULU2PPgo1nifQ
+1Vs+4WD7bPzk5GHl3M3OE2ZwhzYfO+ACcJa29Ahu7GRC660lXKlwONnQYuTTLqPD
+KylY9ZJQUyP+CA5oZsDtnOcfrTy837jKq18NQ3ZxbRDpoVIATNHf9J2qe9yIkxYe
+9p+aXGdvfDsNrhkz/m76V+KmioventOEKsRg64FfGKEZP8EfoBiNJipBdmN1I+GE
+VTW91jjpgBTdCmyncmVn/CaV1d5S4ed4oQMLlLc+KsqDe97bF2TssFxcMmnyxgqb
+bKDZOfzPI1HTs22tj6eLcZTIkcAuFET+uxcmFQcDsjYEf0G+iZLGWw==
 -----END CERTIFICATE-----
index 26b985bf65d32ad13381c5c6bafa67d24eba7b1a..cbb806a9c6c884ff2cb7326f1751aea68b49d01d 100644 (file)
@@ -135,5 +135,17 @@ expected,description, -section,val, -cmd,val,val2, -cacertsout,val,val2, -infoty
 1,reqout_only ir - no server, -section,, -cmd,ir,,-reqout_only,_RESULT_DIR/ir2.der,,BLANK,,BLANK, -server,""""
 0,reqout_only non-existing directory and file, -section,, -cmd,ir,,-reqout_only,idontexist/idontexist,,BLANK,,BLANK, -server,""""
 0,reqin ir - no newkey, -section,, -cmd,ir,,-reqin,_RESULT_DIR/ir2.der,,-newkey,"""",-newkey,"""",-key,"""",-cert,"""",-secret,_PBM_SECRET
-1,reqin ir and rspout - no newkey but -popo -1, -section,, -cmd,ir,,-reqin,_RESULT_DIR/ir2.der,,-rspout,_RESULT_DIR/ip2.der,-newkey,"""",--key,"""",-cert,"""",-secret,_PBM_SECRET,-popo,-1
-1,reqin ip and rspin  - no newkey but -popo -1, -section,, -cmd,ir,,-reqin,_RESULT_DIR/ir2.der,,-rspin,_RESULT_DIR/ip2.der,,-newkey,"""",-key,"""",-cert,"""",-secret,_PBM_SECRET,-popo,-1, -server,"""",-disable_confirm
+1,reqin ir and rspout - using no newkey and -popo 0 as workaround, -section,, -cmd,ir,,-reqin,_RESULT_DIR/ir2.der,,-rspout,_RESULT_DIR/ip2.der,-newkey,"""", -popo,0
+1,reqin ip and rspin  - using no newkey and -popo 0 as workaround, -section,, -cmd,ir,,-reqin,_RESULT_DIR/ir2.der,,-rspin,_RESULT_DIR/ip2.der,,-newkey,"""",-server,"""",-disable_confirm, -popo,0
+1,reqout_only ir - no server with -popo -1 (same as -centralkeygen), -section,, -cmd,ir,,-reqout_only,_RESULT_DIR/ir3.der,,BLANK,,BLANK, -server,"""", -popo,-1, -newkeyout,_RESULT_DIR/dummyout.pem
+1,reqin ir and rspout - using no newkey and -popo -1 (same as -centralkeygen), -section,, -cmd,ir,,-reqin,_RESULT_DIR/ir3.der,,-rspout,_RESULT_DIR/ip3.der,-newkey,"""", -popo,-1, -newkeyout,_RESULT_DIR/newkeyout.pem
+1,reqin ip and rspin  - using no newkey and -popo -1 (same as -centralkeygen), -section,, -cmd,ir,,-reqin,_RESULT_DIR/ir3.der,,-rspin,_RESULT_DIR/ip3.der,,-newkey,"""",-server,"""",-disable_confirm, -popo,-1, -newkeyout,_RESULT_DIR/newkeyout.pem
+,,,,,,,,,,,,,,,,,,,
+1,central key generation, -section,, -cmd,cr,, -centralkeygen, -newkeyout,_RESULT_DIR/newkeyout1.pem
+0,central key generation missing newkeyout, -section,, -cmd,cr,, -centralkeygen,,BLANK,,BLANK,,BLANK,,BLANK,
+0,using popo 1 with -centralkeygen, -section,, -cmd,cr,, -centralkeygen, -popo,1, -newkeyout,_RESULT_DIR/newkeyout.pem
+1, using popo -1 redundantly with -centralkeygen, -section,, -cmd,cr,, -centralkeygen, -popo,-1, -newkeyout,_RESULT_DIR/newkeyout2.pem
+1, using popo -1 alternatively to -centralkeygen, -section,, -cmd,cr,, -popo,-1, -newkeyout,_RESULT_DIR/newkeyout3.pem, -newkeypass,pass:12345, -certout,_RESULT_DIR/test.cert3.pem
+1, using centrally generated key (and cert) , -section,, -cmd,cr,,-cert,_RESULT_DIR/test.cert3.pem, -key,_RESULT_DIR/newkeyout3.pem, -keypass,pass:12345
+0, using centrally generated key with wrong password, -section,, -cmd,cr,,-cert,_RESULT_DIR/test.cert3.pem, -key,_RESULT_DIR/newkeyout3.pem, -keypass,pass:wrong
+0, using popo -1 (instead of -centralkeygen) without -newkeyout, -section,, -cmd,cr,, -popo,-1,,BLANK,,BLANK,,BLANK,,BLANK
index 7e4d850800a8be4f91b26a01a03ffd84a2d823d2..6e9a8a121a3b79f161431c1507e4d8a11795bc8d 100644 (file)
@@ -5734,6 +5734,17 @@ EVP_CIPHER_CTX_get_algor                5861     3_4_0   EXIST::FUNCTION:
 EVP_PKEY_CTX_set_algor_params           5862   3_4_0   EXIST::FUNCTION:
 EVP_PKEY_CTX_get_algor_params           5863   3_4_0   EXIST::FUNCTION:
 EVP_PKEY_CTX_get_algor                  5864   3_4_0   EXIST::FUNCTION:
+d2i_OSSL_CRMF_ENCRYPTEDKEY              ?      3_5_0   EXIST::FUNCTION:CRMF
+i2d_OSSL_CRMF_ENCRYPTEDKEY              ?      3_5_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_ENCRYPTEDKEY_free             ?      3_5_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_ENCRYPTEDKEY_new              ?      3_5_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_ENCRYPTEDKEY_it               ?      3_5_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_ENCRYPTEDKEY_get1_encCert     ?      3_5_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_ENCRYPTEDVALUE_decrypt        ?      3_5_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_ENCRYPTEDKEY_get1_pkey        ?      3_5_0   EXIST::FUNCTION:CRMF
+OSSL_CRMF_MSG_centralkeygen_requested   ?      3_5_0   EXIST::FUNCTION:CRMF
+CMS_EnvelopedData_dup                   ?      3_5_0   EXIST::FUNCTION:CMS
+OSSL_CRMF_ENCRYPTEDKEY_init_envdata     ?      3_5_0   EXIST::FUNCTION:CMS,CRMF
 EVP_get1_default_properties             ?      3_5_0   EXIST::FUNCTION:
 X509_PURPOSE_get_unused_id              ?      3_5_0   EXIST::FUNCTION:
 d2i_OSSL_AUTHORITY_ATTRIBUTE_ID_SYNTAX  ?      3_5_0   EXIST::FUNCTION: