Skip to content

Commit

Permalink
fixup! CMP: add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
rajeev-0 committed Sep 3, 2024
1 parent 8bb6628 commit 9b9511f
Show file tree
Hide file tree
Showing 28 changed files with 234 additions and 197 deletions.
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ OpenSSL Releases
- [OpenSSL 1.0.0](#openssl-100)
- [OpenSSL 0.9.x](#openssl-09x)

OpenSSL 3.5
-----------

### Changes between 3.4 and 3.5 [xx XXX xxxx]

* Added support for central key generation in CMP.

This work was sponsored by Siemens AG.

*Rajeev Ranjan*

OpenSSL 3.4
-----------

Expand Down
50 changes: 30 additions & 20 deletions apps/cmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ static char *opt_srv_trusted = NULL;
static char *opt_srv_untrusted = NULL;
static char *opt_ref_cert = NULL;
static char *opt_rsp_cert = NULL;
static char *opt_rsp_cert_key = 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;
Expand Down Expand Up @@ -286,7 +286,7 @@ typedef enum OPTION_choice {
OPT_SRV_REF, OPT_SRV_SECRET,
OPT_SRV_CERT, OPT_SRV_KEY, OPT_SRV_KEYPASS,
OPT_SRV_TRUSTED, OPT_SRV_UNTRUSTED,
OPT_REF_CERT, OPT_RSP_CERT, OPT_RSP_CERT_KEY, OPT_RSP_KEYPASS,
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,
Expand Down Expand Up @@ -334,7 +334,7 @@ const OPTIONS cmp_options[] = {
{"centralkeygen", OPT_CENTRALKEYGEN, '-',
"Request central (server-side) key generation. Default is local generation"},
{"newkeyout", OPT_NEWKEYOUT, 's',
"File to save new key generated in central key generation"},
"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,
Expand Down Expand Up @@ -580,7 +580,7 @@ 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_cert_key", OPT_RSP_CERT_KEY, 's',
{"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"},
Expand Down Expand Up @@ -698,7 +698,7 @@ 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_cert_key}, {&opt_rsp_keypass},
{&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},

Expand Down Expand Up @@ -1217,13 +1217,13 @@ static OSSL_CMP_SRV_CTX *setup_srv_ctx(ENGINE *engine)
(add_X509_fn_t)ossl_cmp_mock_srv_set1_certOut))
goto err;
}
if (opt_rsp_cert_key != NULL) {
EVP_PKEY *pkey = load_key_pwd(opt_rsp_cert_key, opt_keyform,
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_certOutKey(srv_ctx, pkey)) {
|| !ossl_cmp_mock_srv_set1_keyOut(srv_ctx, pkey)) {
EVP_PKEY_free(pkey);
goto err;
}
Expand Down Expand Up @@ -1704,11 +1704,11 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
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."
"Neither central key generation is requested.");
" Neither central key generation is requested.");
return 0;
}
if (opt_popo == OSSL_CRMF_POPO_NONE && !opt_centralkeygen) {
CMP_info("POPO is disabled, using -centralkeygen");
CMP_info("POPO is disabled, which implies -centralkeygen");
opt_centralkeygen = 1;
}
if (opt_centralkeygen) {
Expand All @@ -1717,7 +1717,7 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine)
return 0;
}
if (opt_newkeyout == NULL) {
CMP_err("-newkeyout not given, nowhere to save newly generated key");
CMP_err("-newkeyout not given, nowhere to save centrally generated key");
return 0;
}
opt_popo = OSSL_CRMF_POPO_NONE;
Expand Down Expand Up @@ -1769,8 +1769,10 @@ 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("-centralkeygen %s", msg);
CMP_warn1("-popo -1 or -centralkeygen %s", msg);
if (opt_newkeyout != NULL)
CMP_warn1("-newkeyout %s", msg);
if (opt_cmd != CMP_P10CR) {
Expand Down Expand Up @@ -1877,7 +1879,7 @@ 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;
Expand Down Expand Up @@ -3141,8 +3143,8 @@ static int get_opts(int argc, char **argv)
case OPT_RSP_CERT:
opt_rsp_cert = opt_str();
break;
case OPT_RSP_CERT_KEY:
opt_rsp_cert_key = opt_str();
case OPT_RSP_KEY:
opt_rsp_key = opt_str();
break;
case OPT_RSP_KEYPASS:
opt_rsp_keypass = opt_str();
Expand Down Expand Up @@ -3855,17 +3857,25 @@ int cmp_main(int argc, char **argv)
opt_cacertsout, "CA") < 0)
goto err;
if (opt_centralkeygen) {
const EVP_CIPHER *cipher = NULL;
char *pass_string = NULL;
EVP_PKEY *new_key = OSSL_CMP_CTX_get0_newPkey(cmp_ctx, 1 /* priv */);
BIO *out = bio_open_owner(opt_newkeyout, FORMAT_PEM, 1);

if (out == NULL)
if (new_key == NULL || out == NULL)
goto err;
CMP_info1("received central (server) generated key, saving to file '%s'",
opt_newkeyout);
if (PEM_write_bio_PrivateKey(out, new_key, NULL, NULL, 0, NULL,
NULL) <= 0)
if (opt_newkeypass != NULL) {
pass_string = get_passwd(opt_newkeypass,
"Centrally generated private key password");
cipher = EVP_aes_256_cbc();
}

CMP_info1("saving centrally generated key to file '%s'", opt_newkeyout);
if (PEM_write_bio_PKCS8PrivateKey(out, new_key, cipher, NULL, 0, NULL,
(void *)pass_string) <= 0)
goto err;
BIO_free(out);
clear_free(pass_string);
}
}
if (!OSSL_CMP_CTX_reinit(cmp_ctx))
Expand Down
3 changes: 1 addition & 2 deletions apps/include/cmp_mock_srv.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +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_certOutKey(OSSL_CMP_SRV_CTX *srv_ctx,
EVP_PKEY *pkey);
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);
Expand Down
24 changes: 13 additions & 11 deletions apps/lib/cmp_mock_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +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 *certOutKey; /* Private key to be returned for central keygen */
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 */
Expand Down Expand Up @@ -88,8 +88,7 @@ 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_certOutKey(OSSL_CMP_SRV_CTX *srv_ctx,
EVP_PKEY *pkey)
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);

Expand All @@ -99,8 +98,8 @@ int ossl_cmp_mock_srv_set1_certOutKey(OSSL_CMP_SRV_CTX *srv_ctx,
}
if (pkey != NULL && !EVP_PKEY_up_ref(pkey))
return 0;
EVP_PKEY_free(ctx->certOutKey);
ctx->certOutKey = pkey;
EVP_PKEY_free(ctx->keyOut);
ctx->keyOut = pkey;
return 1;
}

Expand Down Expand Up @@ -292,7 +291,7 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx);
int bodytype;
OSSL_CMP_PKISI *si = NULL;
EVP_PKEY *certOutKey = NULL;
EVP_PKEY *keyOut = NULL;

if (ctx == NULL || cert_req == NULL
|| certOut == NULL || chainOut == NULL || caPubs == NULL) {
Expand Down Expand Up @@ -376,13 +375,16 @@ 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;
if (ctx->certOutKey != NULL
&& OSSL_CMP_SRV_CTX_centralKeygen_req(crm, (X509_REQ *) p10cr)
/* using newPkey to return the private key */
&& (((certOutKey = EVP_PKEY_dup(ctx->certOutKey)) == NULL)
if (OSSL_CMP_SRV_CTX_centralKeygen_req(crm, p10cr)
&& (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 */, certOutKey)))
1 /* priv */, 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;
Expand Down
3 changes: 1 addition & 2 deletions crypto/cmp/cmp_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,6 @@ static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype,
{
char buf[OSSL_CMP_PKISI_BUFLEN];
X509 *crt = NULL;
EVP_PKEY *privkey = NULL;

if (!ossl_assert(ctx != NULL && crep != NULL))
return NULL;
Expand Down Expand Up @@ -547,7 +546,7 @@ static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype,
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_PKISTATUS);
goto err;
}
crt = ossl_cmp_certresponse_get1_cert_key(crep, ctx, privkey);
crt = ossl_cmp_certresponse_get1_cert(ctx, crep);
if (crt == NULL) /* according to PKIStatus, we can expect a cert */
ERR_raise(ERR_LIB_CMP, CMP_R_CERTIFICATE_NOT_FOUND);

Expand Down
7 changes: 4 additions & 3 deletions crypto/cmp/cmp_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ 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, EVP_PKEY *certkey,
X509 *cert, const EVP_PKEY *pkey,
const X509 *encryption_recip,
STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
int unprotectedErrors);
Expand Down Expand Up @@ -989,12 +989,13 @@ ossl_cmp_pollrepcontent_get0_pollrep(const OSSL_CMP_POLLREPCONTENT *prc,
OSSL_CMP_CERTRESPONSE *
ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
int rid);
X509 *ossl_cmp_certresponse_get1_cert_key(const OSSL_CMP_CERTRESPONSE *crep,
const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey);
X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_CERTRESPONSE *crep);
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);
Expand Down
49 changes: 26 additions & 23 deletions crypto/cmp/cmp_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,34 +453,37 @@ OSSL_CMP_MSG *ossl_cmp_certreq_new(OSSL_CMP_CTX *ctx, int type,
}

#ifndef OPENSSL_NO_CMS
static OSSL_CRMF_ENCRYPTEDKEY *encprivatekey(OSSL_CMP_CTX *ctx, EVP_PKEY *privKey)
static OSSL_CRMF_ENCRYPTEDKEY *enc_privkey(OSSL_CMP_CTX *ctx, const EVP_PKEY *pkey)
{
OSSL_CRMF_ENCRYPTEDKEY *ek = NULL;
CMS_EnvelopedData *envData = NULL;
STACK_OF(X509) *encryption_recips = NULL;
BIO *privbio = NULL;
int res = 0;
X509 *recip = X509_dup(ctx->validatedSrvCert);
STACK_OF(X509) * encryption_recips = sk_X509_new_null();

if (encryption_recips == NULL || recip == NULL)
goto err;

encryption_recips = sk_X509_new_null();
if (encryption_recips == NULL || recip == NULL
|| !sk_X509_push(encryption_recips, recip))
if (!sk_X509_push(encryption_recips, recip))
goto err;
recip = NULL;

privbio = BIO_new(BIO_s_mem());
if (privbio == NULL || i2d_PrivateKey_bio(privbio, privKey) <= 0)
if (privbio == NULL || i2d_PrivateKey_bio(privbio, pkey) <= 0)
goto err;
envData = CMS_env_sign_data(privbio, ctx->cert, ctx->pkey,
encryption_recips, ctx->libctx, ctx->propq);
ossl_cmp_set_own_chain(ctx);
envData = CMS_sign_encrypt(privbio, ctx->cert, ctx->chain, ctx->pkey, CMS_BINARY,
encryption_recips, EVP_aes_256_cbc(), CMS_BINARY,
ctx->libctx, ctx->propq);
if (envData == NULL)
goto err;
if ((ek = OSSL_CRMF_ENCRYPTEDKEY_init_envdata(envData)) == NULL)
goto err;
res = 1;
ek = OSSL_CRMF_ENCRYPTEDKEY_init_envdata(envData);

err:
sk_X509_pop_free(encryption_recips, X509_free);
if (!res)
X509_free(recip);
BIO_free(privbio);
if (ek == NULL)
M_ASN1_free_of(envData, CMS_EnvelopedData);

return ek;
Expand All @@ -489,7 +492,7 @@ static OSSL_CRMF_ENCRYPTEDKEY *encprivatekey(OSSL_CMP_CTX *ctx, EVP_PKEY *privKe

OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
int certReqId, const OSSL_CMP_PKISI *si,
X509 *cert, EVP_PKEY *certkey,
X509 *cert, const EVP_PKEY *pkey,
const X509 *encryption_recip,
STACK_OF(X509) *chain, STACK_OF(X509) *caPubs,
int unprotectedErrors)
Expand Down Expand Up @@ -535,9 +538,10 @@ OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
goto err;
resp->certifiedKeyPair->certOrEncCert->value.certificate = cert;

if (certkey != NULL) {
if (pkey != NULL) {
#ifndef OPENSSL_NO_CMS
resp->certifiedKeyPair->privateKey = encprivatekey(ctx, certkey);
if ((resp->certifiedKeyPair->privateKey = enc_privkey(ctx, pkey)) == NULL)
goto err;
#else
ERR_raise(ERR_LIB_CMP, ERR_R_UNSUPPORTED);
goto err;
Expand Down Expand Up @@ -1100,16 +1104,16 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,

/*-
* Retrieve newly enrolled certificate and key from the given certResponse crep.
* In case of indirect POPO uses the libctx and propq from ctx and private key.
* In case of central key generation, updates ctx->newPkey.
* 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_key(const OSSL_CMP_CERTRESPONSE *crep,
const OSSL_CMP_CTX *ctx, EVP_PKEY *pkey)
X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx, const OSSL_CMP_CERTRESPONSE *crep)
{
OSSL_CMP_CERTORENCCERT *coec;
X509 *crt = NULL;
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;

Expand Down Expand Up @@ -1156,9 +1160,8 @@ X509 *ossl_cmp_certresponse_get1_cert_key(const OSSL_CMP_CERTRESPONSE *crep,
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PRIVATE_KEY);
return NULL;
}
crt = OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(coec->value.encryptedCert,
ctx->libctx, ctx->propq,
pkey, 0);
crt = OSSL_CRMF_ENCRYPTEDKEY_get1_encCert(coec->value.encryptedCert, pkey, 0,
ctx->libctx, ctx->propq);
break;
default:
ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_CERT_TYPE);
Expand Down
Loading

0 comments on commit 9b9511f

Please sign in to comment.