CMP: add support for central key generation

- 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)
This commit is contained in:
Rajeev Ranjan 2024-05-29 18:19:29 +02:00 committed by Tomas Mraz
parent 35b97122ea
commit 0048817523
37 changed files with 966 additions and 153 deletions

View 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

View 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;

View 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);

View 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;

View 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)

View 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))) {

View 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),

View 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);

View 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);

View 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;

View 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;

View 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),

View 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;
}

View 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)

View 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
@ -18,44 +18,57 @@
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}
};

View 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)
goto end;
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

View 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

View 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

View file

@ -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

View 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.

View 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.

View 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,

View 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.

View 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

View 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.

View 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

View 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(),

22
include/internal/cms.h Normal file
View file

@ -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 */

View 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
@ -103,6 +105,7 @@
# 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

View 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

View 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
}

View file

@ -24,16 +24,23 @@
* 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

View 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)$/;

View 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

View 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-----

View 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

Can't render this file because it has a wrong number of fields in line 2.

View 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: