*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
/* 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;
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;
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,
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,
{"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,
"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',
{&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},
{&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},
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;
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) {
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);
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;
}
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;
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;
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;
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);
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 */
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)
{
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) {
&& (*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;
/* 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)
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)
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;
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))) {
{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),
{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"},
"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),
int type;
union {
X509 *certificate;
- OSSL_CRMF_ENCRYPTEDVALUE *encryptedCert;
+ OSSL_CRMF_ENCRYPTEDKEY *encryptedCert;
} value;
} OSSL_CMP_CERTORENCCERT;
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)
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);
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);
#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)
{
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);
: 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;
}
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
|| !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);
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)
{
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))
}
/*-
- * 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);
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);
}
}
+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)
{
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;
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;
}
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,
/* 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)
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;
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),
#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);
*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;
+}
} 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)
/*
* 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}
};
#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"
#include <openssl/crmf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
+#include <openssl/cms.h>
/*-
* atyp = Attribute Type
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)
{
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);
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, out, outlen,
+ 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
# 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 */
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
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
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
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
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
--- /dev/null
+=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
[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>]
[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>]
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
=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.
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.
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>.
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.
=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.
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,
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
*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
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)>).
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
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.
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
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.
CMS_ContentInfo_new_ex,
CMS_ContentInfo_print_ctx,
CMS_EnvelopedData_it,
+CMS_EnvelopedData_dup,
CMS_ReceiptRequest_free,
CMS_ReceiptRequest_new,
CMS_SignedData_free,
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,
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
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,
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,
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(),
--- /dev/null
+/*
+ * 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 */
# 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
# 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
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
# 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>
# 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)
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
}
* 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
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)$/;
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
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-----
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
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: