summaryrefslogtreecommitdiff
path: root/crypto/cmp
diff options
context:
space:
mode:
authorEnji Cooper <ngie@FreeBSD.org>2025-05-07 21:18:24 +0000
committerEnji Cooper <ngie@FreeBSD.org>2025-05-07 22:37:22 +0000
commit29536654cc41bf41b92dc836c47496dc6fe0b00c (patch)
tree368a3c5b14e610bb5f6b71657f61a41e373eaf97 /crypto/cmp
parent1c34280346af8284acdc0eae39496811d37df25d (diff)
Diffstat (limited to 'crypto/cmp')
-rw-r--r--crypto/cmp/build.info11
-rw-r--r--crypto/cmp/cmp_asn.c695
-rw-r--r--crypto/cmp/cmp_client.c227
-rw-r--r--crypto/cmp/cmp_ctx.c475
-rw-r--r--crypto/cmp/cmp_err.c29
-rw-r--r--crypto/cmp/cmp_hdr.c50
-rw-r--r--crypto/cmp/cmp_http.c46
-rw-r--r--crypto/cmp/cmp_local.h112
-rw-r--r--crypto/cmp/cmp_msg.c269
-rw-r--r--crypto/cmp/cmp_protect.c115
-rw-r--r--crypto/cmp/cmp_server.c259
-rw-r--r--crypto/cmp/cmp_status.c10
-rw-r--r--crypto/cmp/cmp_util.c8
-rw-r--r--crypto/cmp/cmp_vfy.c268
14 files changed, 1797 insertions, 777 deletions
diff --git a/crypto/cmp/build.info b/crypto/cmp/build.info
index a2a57c14ec10..907d78d25ffb 100644
--- a/crypto/cmp/build.info
+++ b/crypto/cmp/build.info
@@ -1,4 +1,11 @@
LIBS=../../libcrypto
-SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \
+$OPENSSLSRC=\
+ cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \
cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c \
- cmp_server.c cmp_client.c cmp_http.c
+ cmp_server.c cmp_client.c cmp_genm.c
+
+IF[{- !$disabled{'http'} -}]
+ $OPENSSLSRC=$OPENSSLSRC cmp_http.c
+ENDIF
+
+SOURCE[../../libcrypto]=$OPENSSLSRC
diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c
index a8de73ad979b..a32632026743 100644
--- a/crypto/cmp/cmp_asn.c
+++ b/crypto/cmp/cmp_asn.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -12,6 +12,7 @@
#include <openssl/asn1t.h>
#include "cmp_local.h"
+#include "internal/crmf.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/cmp.h>
@@ -28,7 +29,6 @@ ASN1_SEQUENCE(OSSL_CMP_REVANNCONTENT) = {
} ASN1_SEQUENCE_END(OSSL_CMP_REVANNCONTENT)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVANNCONTENT)
-
ASN1_SEQUENCE(OSSL_CMP_CHALLENGE) = {
ASN1_OPT(OSSL_CMP_CHALLENGE, owf, X509_ALGOR),
ASN1_SIMPLE(OSSL_CMP_CHALLENGE, witness, ASN1_OCTET_STRING),
@@ -36,19 +36,16 @@ ASN1_SEQUENCE(OSSL_CMP_CHALLENGE) = {
} ASN1_SEQUENCE_END(OSSL_CMP_CHALLENGE)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CHALLENGE)
-
ASN1_ITEM_TEMPLATE(OSSL_CMP_POPODECKEYCHALLCONTENT) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
OSSL_CMP_POPODECKEYCHALLCONTENT, OSSL_CMP_CHALLENGE)
ASN1_ITEM_TEMPLATE_END(OSSL_CMP_POPODECKEYCHALLCONTENT)
-
ASN1_ITEM_TEMPLATE(OSSL_CMP_POPODECKEYRESPCONTENT) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
OSSL_CMP_POPODECKEYRESPCONTENT, ASN1_INTEGER)
ASN1_ITEM_TEMPLATE_END(OSSL_CMP_POPODECKEYRESPCONTENT)
-
ASN1_SEQUENCE(OSSL_CMP_CAKEYUPDANNCONTENT) = {
/* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
ASN1_SIMPLE(OSSL_CMP_CAKEYUPDANNCONTENT, oldWithNew, X509),
@@ -59,15 +56,10 @@ ASN1_SEQUENCE(OSSL_CMP_CAKEYUPDANNCONTENT) = {
} ASN1_SEQUENCE_END(OSSL_CMP_CAKEYUPDANNCONTENT)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
-
ASN1_SEQUENCE(OSSL_CMP_ERRORMSGCONTENT) = {
ASN1_SIMPLE(OSSL_CMP_ERRORMSGCONTENT, pKIStatusInfo, OSSL_CMP_PKISI),
ASN1_OPT(OSSL_CMP_ERRORMSGCONTENT, errorCode, ASN1_INTEGER),
- /*
- * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
- * so it is used directly
- *
- */
+ /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */
ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ERRORMSGCONTENT, errorDetails,
ASN1_UTF8STRING)
} ASN1_SEQUENCE_END(OSSL_CMP_ERRORMSGCONTENT)
@@ -119,10 +111,27 @@ ASN1_ADB(OSSL_CMP_ITAV) = {
ADB_ENTRY(NID_id_it_suppLangTags,
ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.suppLangTagsValue,
ASN1_UTF8STRING)),
+ ADB_ENTRY(NID_id_it_caCerts,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.caCerts, X509)),
+ ADB_ENTRY(NID_id_it_rootCaCert,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaCert, X509)),
+ ADB_ENTRY(NID_id_it_rootCaKeyUpdate,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaKeyUpdate,
+ OSSL_CMP_ROOTCAKEYUPDATE)),
+ ADB_ENTRY(NID_id_it_certReqTemplate,
+ ASN1_OPT(OSSL_CMP_ITAV, infoValue.certReqTemplate,
+ OSSL_CMP_CERTREQTEMPLATE)),
+ ADB_ENTRY(NID_id_it_certProfile,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.certProfile,
+ ASN1_UTF8STRING)),
+ ADB_ENTRY(NID_id_it_crlStatusList,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.crlStatusList,
+ OSSL_CMP_CRLSTATUS)),
+ ADB_ENTRY(NID_id_it_crls,
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.crls, X509_CRL))
} ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0,
&infotypeandvalue_default_tt, NULL);
-
ASN1_SEQUENCE(OSSL_CMP_ITAV) = {
ASN1_SIMPLE(OSSL_CMP_ITAV, infoType, ASN1_OBJECT),
ASN1_ADB_OBJECT(OSSL_CMP_ITAV)
@@ -130,6 +139,41 @@ ASN1_SEQUENCE(OSSL_CMP_ITAV) = {
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
+ASN1_SEQUENCE(OSSL_CMP_ROOTCAKEYUPDATE) = {
+ /* OSSL_CMP_CMPCERTIFICATE is effectively X509 so it is used directly */
+ ASN1_SIMPLE(OSSL_CMP_ROOTCAKEYUPDATE, newWithNew, X509),
+ ASN1_EXP_OPT(OSSL_CMP_ROOTCAKEYUPDATE, newWithOld, X509, 0),
+ ASN1_EXP_OPT(OSSL_CMP_ROOTCAKEYUPDATE, oldWithNew, X509, 1)
+} ASN1_SEQUENCE_END(OSSL_CMP_ROOTCAKEYUPDATE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
+
+ASN1_ITEM_TEMPLATE(OSSL_CMP_ATAVS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0,
+ OSSL_CMP_ATAVS, OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+ASN1_ITEM_TEMPLATE_END(OSSL_CMP_ATAVS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_ATAVS)
+
+ASN1_SEQUENCE(OSSL_CMP_CERTREQTEMPLATE) = {
+ ASN1_SIMPLE(OSSL_CMP_CERTREQTEMPLATE, certTemplate, OSSL_CRMF_CERTTEMPLATE),
+ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_CERTREQTEMPLATE, keySpec,
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE)
+} ASN1_SEQUENCE_END(OSSL_CMP_CERTREQTEMPLATE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTREQTEMPLATE)
+
+ASN1_CHOICE(OSSL_CMP_CRLSOURCE) = {
+ ASN1_EXP(OSSL_CMP_CRLSOURCE, value.dpn, DIST_POINT_NAME, 0),
+ ASN1_EXP(OSSL_CMP_CRLSOURCE, value.issuer, GENERAL_NAMES, 1),
+} ASN1_CHOICE_END(OSSL_CMP_CRLSOURCE)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSOURCE)
+#define OSSL_CMP_CRLSOURCE_DPN 0
+#define OSSL_CMP_CRLSOURCE_ISSUER 1
+
+ASN1_SEQUENCE(OSSL_CMP_CRLSTATUS) = {
+ ASN1_SIMPLE(OSSL_CMP_CRLSTATUS, source, OSSL_CMP_CRLSOURCE),
+ ASN1_OPT(OSSL_CMP_CRLSTATUS, thisUpdate, ASN1_TIME)
+} ASN1_SEQUENCE_END(OSSL_CMP_CRLSTATUS)
+IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS)
+
OSSL_CMP_ITAV *OSSL_CMP_ITAV_create(ASN1_OBJECT *type, ASN1_TYPE *value)
{
OSSL_CMP_ITAV *itav;
@@ -181,13 +225,609 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p,
return 1;
err:
- if (created != 0) {
+ if (created) {
sk_OSSL_CMP_ITAV_free(*itav_sk_p);
*itav_sk_p = NULL;
}
return 0;
}
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) *certProfile)
+{
+ OSSL_CMP_ITAV *itav;
+
+ if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+ return NULL;
+ itav->infoType = OBJ_nid2obj(NID_id_it_certProfile);
+ itav->infoValue.certProfile = certProfile;
+ return itav;
+}
+
+int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav,
+ STACK_OF(ASN1_UTF8STRING) **out)
+{
+ if (itav == NULL || out == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (OBJ_obj2nid(itav->infoType) != NID_id_it_certProfile) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ *out = itav->infoValue.certProfile;
+ return 1;
+}
+
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts)
+{
+ OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new();
+
+ if (itav == NULL)
+ return NULL;
+ if (sk_X509_num(caCerts) > 0
+ && (itav->infoValue.caCerts =
+ sk_X509_deep_copy(caCerts, X509_dup, X509_free)) == NULL) {
+ OSSL_CMP_ITAV_free(itav);
+ return NULL;
+ }
+ itav->infoType = OBJ_nid2obj(NID_id_it_caCerts);
+ return itav;
+}
+
+int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out)
+{
+ if (itav == NULL || out == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (OBJ_obj2nid(itav->infoType) != NID_id_it_caCerts) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ *out = sk_X509_num(itav->infoValue.caCerts) > 0
+ ? itav->infoValue.caCerts : NULL;
+ return 1;
+}
+
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaCert(const X509 *rootCaCert)
+{
+ OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new();
+
+ if (itav == NULL)
+ return NULL;
+ if (rootCaCert != NULL
+ && (itav->infoValue.rootCaCert = X509_dup(rootCaCert)) == NULL) {
+ OSSL_CMP_ITAV_free(itav);
+ return NULL;
+ }
+ itav->infoType = OBJ_nid2obj(NID_id_it_rootCaCert);
+ return itav;
+}
+
+int OSSL_CMP_ITAV_get0_rootCaCert(const OSSL_CMP_ITAV *itav, X509 **out)
+{
+ if (itav == NULL || out == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (OBJ_obj2nid(itav->infoType) != NID_id_it_rootCaCert) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ *out = itav->infoValue.rootCaCert;
+ return 1;
+}
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_rootCaKeyUpdate(const X509 *newWithNew,
+ const X509 *newWithOld,
+ const X509 *oldWithNew)
+{
+ OSSL_CMP_ITAV *itav;
+ OSSL_CMP_ROOTCAKEYUPDATE *upd = NULL;
+
+ if (newWithNew != NULL) {
+ upd = OSSL_CMP_ROOTCAKEYUPDATE_new();
+ if (upd == NULL)
+ return NULL;
+
+ if ((upd->newWithNew = X509_dup(newWithNew)) == NULL)
+ goto err;
+ if (newWithOld != NULL
+ && (upd->newWithOld = X509_dup(newWithOld)) == NULL)
+ goto err;
+ if (oldWithNew != NULL
+ && (upd->oldWithNew = X509_dup(oldWithNew)) == NULL)
+ goto err;
+ }
+
+ if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+ goto err;
+ itav->infoType = OBJ_nid2obj(NID_id_it_rootCaKeyUpdate);
+ itav->infoValue.rootCaKeyUpdate = upd;
+ return itav;
+
+ err:
+ OSSL_CMP_ROOTCAKEYUPDATE_free(upd);
+ return NULL;
+}
+
+int OSSL_CMP_ITAV_get0_rootCaKeyUpdate(const OSSL_CMP_ITAV *itav,
+ X509 **newWithNew,
+ X509 **newWithOld,
+ X509 **oldWithNew)
+{
+ OSSL_CMP_ROOTCAKEYUPDATE *upd;
+
+ if (itav == NULL || newWithNew == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (OBJ_obj2nid(itav->infoType) != NID_id_it_rootCaKeyUpdate) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ upd = itav->infoValue.rootCaKeyUpdate;
+ *newWithNew = upd != NULL ? upd->newWithNew : NULL;
+ if (newWithOld != NULL)
+ *newWithOld = upd != NULL ? upd->newWithOld : NULL;
+ if (oldWithNew != NULL)
+ *oldWithNew = upd != NULL ? upd->oldWithNew : NULL;
+ return 1;
+}
+
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_certReqTemplate(OSSL_CRMF_CERTTEMPLATE *certTemplate,
+ OSSL_CMP_ATAVS *keySpec)
+{
+ OSSL_CMP_ITAV *itav;
+ OSSL_CMP_CERTREQTEMPLATE *tmpl;
+
+ if (certTemplate == NULL && keySpec != NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+ if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+ return NULL;
+ itav->infoType = OBJ_nid2obj(NID_id_it_certReqTemplate);
+ if (certTemplate == NULL)
+ return itav;
+
+ if ((tmpl = OSSL_CMP_CERTREQTEMPLATE_new()) == NULL) {
+ OSSL_CMP_ITAV_free(itav);
+ return NULL;
+ }
+ itav->infoValue.certReqTemplate = tmpl;
+ tmpl->certTemplate = certTemplate;
+ tmpl->keySpec = keySpec;
+ return itav;
+}
+
+int OSSL_CMP_ITAV_get1_certReqTemplate(const OSSL_CMP_ITAV *itav,
+ OSSL_CRMF_CERTTEMPLATE **certTemplate,
+ OSSL_CMP_ATAVS **keySpec)
+{
+ OSSL_CMP_CERTREQTEMPLATE *tpl;
+
+ if (itav == NULL || certTemplate == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+
+ *certTemplate = NULL;
+ if (keySpec != NULL)
+ *keySpec = NULL;
+
+ if (OBJ_obj2nid(itav->infoType) != NID_id_it_certReqTemplate) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ tpl = itav->infoValue.certReqTemplate;
+ if (tpl == NULL) /* no requirements available */
+ return 1;
+
+ if ((*certTemplate = OSSL_CRMF_CERTTEMPLATE_dup(tpl->certTemplate)) == NULL)
+ return 0;
+ if (keySpec != NULL && tpl->keySpec != NULL) {
+ int i, n = sk_OSSL_CMP_ATAV_num(tpl->keySpec);
+
+ *keySpec = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_reserve(NULL, n);
+ if (*keySpec == NULL)
+ goto err;
+ for (i = 0; i < n; i++) {
+ OSSL_CMP_ATAV *atav = sk_OSSL_CMP_ATAV_value(tpl->keySpec, i);
+ ASN1_OBJECT *type = OSSL_CMP_ATAV_get0_type(atav /* may be NULL */);
+ int nid;
+ const char *name;
+
+ if (type == NULL) {
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_KEYSPEC,
+ "keySpec with index %d in certReqTemplate does not exist",
+ i);
+ goto err;
+ }
+ nid = OBJ_obj2nid(type);
+
+ if (nid != NID_id_regCtrl_algId
+ && nid != NID_id_regCtrl_rsaKeyLen) {
+ name = OBJ_nid2ln(nid);
+ if (name == NULL)
+ name = OBJ_nid2sn(nid);
+ if (name == NULL)
+ name = "<undef>";
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_INVALID_KEYSPEC,
+ "keySpec with index %d in certReqTemplate has invalid type %s",
+ i, name);
+ goto err;
+ }
+ OSSL_CMP_ATAV_push1(keySpec, atav);
+ }
+ }
+ return 1;
+
+ err:
+ OSSL_CRMF_CERTTEMPLATE_free(*certTemplate);
+ *certTemplate = NULL;
+ sk_OSSL_CMP_ATAV_pop_free(*keySpec, OSSL_CMP_ATAV_free);
+ if (keySpec != NULL)
+ *keySpec = NULL;
+ return 0;
+}
+
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_create(ASN1_OBJECT *type, ASN1_TYPE *value)
+{
+ OSSL_CMP_ATAV *atav;
+
+ if ((atav = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new()) == NULL)
+ return NULL;
+ OSSL_CMP_ATAV_set0(atav, type, value);
+ return atav;
+}
+
+void OSSL_CMP_ATAV_set0(OSSL_CMP_ATAV *atav, ASN1_OBJECT *type,
+ ASN1_TYPE *value)
+{
+ atav->type = type;
+ atav->value.other = value;
+}
+
+ASN1_OBJECT *OSSL_CMP_ATAV_get0_type(const OSSL_CMP_ATAV *atav)
+{
+ if (atav == NULL)
+ return NULL;
+ return atav->type;
+}
+
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_algId(const X509_ALGOR *alg)
+{
+ X509_ALGOR *dup;
+ OSSL_CMP_ATAV *res;
+
+ if (alg == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ if ((dup = X509_ALGOR_dup(alg)) == NULL)
+ return NULL;
+ res = OSSL_CMP_ATAV_create(OBJ_nid2obj(NID_id_regCtrl_algId),
+ (ASN1_TYPE *)dup);
+ if (res == NULL)
+ X509_ALGOR_free(dup);
+ return res;
+}
+
+X509_ALGOR *OSSL_CMP_ATAV_get0_algId(const OSSL_CMP_ATAV *atav)
+{
+ if (atav == NULL || OBJ_obj2nid(atav->type) != NID_id_regCtrl_algId)
+ return NULL;
+ return atav->value.algId;
+}
+
+OSSL_CMP_ATAV *OSSL_CMP_ATAV_new_rsaKeyLen(int len)
+{
+ ASN1_INTEGER *aint;
+ OSSL_CMP_ATAV *res = NULL;
+
+ if (len <= 0) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+ if ((aint = ASN1_INTEGER_new()) == NULL)
+ return NULL;
+ if (!ASN1_INTEGER_set(aint, len)
+ || (res = OSSL_CMP_ATAV_create(OBJ_nid2obj(NID_id_regCtrl_rsaKeyLen),
+ (ASN1_TYPE *)aint)) == NULL)
+ ASN1_INTEGER_free(aint);
+ return res;
+}
+
+int OSSL_CMP_ATAV_get_rsaKeyLen(const OSSL_CMP_ATAV *atav)
+{
+ int64_t val;
+
+ if (atav == NULL || OBJ_obj2nid(atav->type) != NID_id_regCtrl_rsaKeyLen
+ || !ASN1_INTEGER_get_int64(&val, atav->value.rsaKeyLen))
+ return -1;
+ if (val <= 0 || val > INT_MAX)
+ return -2;
+ return (int)val;
+}
+
+ASN1_TYPE *OSSL_CMP_ATAV_get0_value(const OSSL_CMP_ATAV *atav)
+{
+ if (atav == NULL)
+ return NULL;
+ return atav->value.other;
+}
+
+int OSSL_CMP_ATAV_push1(OSSL_CMP_ATAVS **sk_p, const OSSL_CMP_ATAV *atav)
+{
+ int created = 0;
+ OSSL_CMP_ATAV *dup;
+
+ if (sk_p == NULL || atav == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ goto err;
+ }
+
+ if (*sk_p == NULL) {
+ if ((*sk_p = sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_new_null()) == NULL)
+ goto err;
+ created = 1;
+ }
+
+ if ((dup = OSSL_CRMF_ATTRIBUTETYPEANDVALUE_dup((OSSL_CRMF_ATTRIBUTETYPEANDVALUE *)atav)) == NULL)
+ goto err;
+ if (sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_push(*sk_p, dup))
+ return 1;
+ OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(dup);
+
+ err:
+ if (created) {
+ sk_OSSL_CRMF_ATTRIBUTETYPEANDVALUE_free(*sk_p);
+ *sk_p = NULL;
+ }
+ return 0;
+}
+
+OSSL_CMP_ITAV
+*OSSL_CMP_ITAV_new0_crlStatusList(STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList)
+{
+ OSSL_CMP_ITAV *itav;
+
+ if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+ return NULL;
+ itav->infoType = OBJ_nid2obj(NID_id_it_crlStatusList);
+ itav->infoValue.crlStatusList = crlStatusList;
+ return itav;
+}
+
+int OSSL_CMP_ITAV_get0_crlStatusList(const OSSL_CMP_ITAV *itav,
+ STACK_OF(OSSL_CMP_CRLSTATUS) **out)
+{
+ if (itav == NULL || out == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (OBJ_obj2nid(itav->infoType) != NID_id_it_crlStatusList) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ *out = itav->infoValue.crlStatusList;
+ return 1;
+}
+
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_new1(const DIST_POINT_NAME *dpn,
+ const GENERAL_NAMES *issuer,
+ const ASN1_TIME *thisUpdate)
+{
+ OSSL_CMP_CRLSOURCE *crlsource;
+ OSSL_CMP_CRLSTATUS *crlstatus;
+
+ if (dpn == NULL && issuer == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (dpn != NULL && issuer != NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return NULL;
+ }
+
+ if ((crlstatus = OSSL_CMP_CRLSTATUS_new()) == NULL)
+ return NULL;
+ crlsource = crlstatus->source;
+
+ if (dpn != NULL) {
+ crlsource->type = OSSL_CMP_CRLSOURCE_DPN;
+ if ((crlsource->value.dpn = DIST_POINT_NAME_dup(dpn)) == NULL)
+ goto err;
+ } else {
+ crlsource->type = OSSL_CMP_CRLSOURCE_ISSUER;
+ if ((crlsource->value.issuer =
+ sk_GENERAL_NAME_deep_copy(issuer, GENERAL_NAME_dup,
+ GENERAL_NAME_free)) == NULL)
+ goto err;
+ }
+
+ if (thisUpdate != NULL
+ && (crlstatus->thisUpdate = ASN1_TIME_dup(thisUpdate)) == NULL)
+ goto err;
+ return crlstatus;
+
+ err:
+ OSSL_CMP_CRLSTATUS_free(crlstatus);
+ return NULL;
+}
+
+static GENERAL_NAMES *gennames_new(const X509_NAME *nm)
+{
+ GENERAL_NAMES *names;
+ GENERAL_NAME *name = NULL;
+
+ if ((names = sk_GENERAL_NAME_new_reserve(NULL, 1)) == NULL)
+ return NULL;
+ if (!GENERAL_NAME_set1_X509_NAME(&name, nm)) {
+ sk_GENERAL_NAME_free(names);
+ return NULL;
+ }
+ (void)sk_GENERAL_NAME_push(names, name); /* cannot fail */
+ return names;
+}
+
+static int gennames_allowed(GENERAL_NAMES *names, int only_DN)
+{
+ if (names == NULL)
+ return 0;
+ if (!only_DN)
+ return 1;
+ return sk_GENERAL_NAME_num(names) == 1
+ && sk_GENERAL_NAME_value(names, 0)->type == GEN_DIRNAME;
+}
+
+OSSL_CMP_CRLSTATUS *OSSL_CMP_CRLSTATUS_create(const X509_CRL *crl,
+ const X509 *cert, int only_DN)
+{
+ STACK_OF(DIST_POINT) *crldps = NULL;
+ ISSUING_DIST_POINT *idp = NULL;
+ DIST_POINT_NAME *dpn = NULL;
+ AUTHORITY_KEYID *akid = NULL;
+ GENERAL_NAMES *issuers = NULL;
+ const GENERAL_NAMES *CRLissuer = NULL;
+ const ASN1_TIME *last = crl == NULL ? NULL : X509_CRL_get0_lastUpdate(crl);
+ OSSL_CMP_CRLSTATUS *status = NULL;
+ int i, NID_akid = NID_authority_key_identifier;
+
+ /*
+ * Note:
+ * X509{,_CRL}_get_ext_d2i(..., NID, ..., NULL) return the 1st extension with
+ * given NID that is available, if any. If there are more, this is an error.
+ */
+ if (cert != NULL) {
+ crldps = X509_get_ext_d2i(cert, NID_crl_distribution_points, NULL, NULL);
+ /* if available, take the first suitable element */
+ for (i = 0; i < sk_DIST_POINT_num(crldps); i++) {
+ DIST_POINT *dp = sk_DIST_POINT_value(crldps, i);
+
+ if (dp == NULL)
+ continue;
+ if ((dpn = dp->distpoint) != NULL) {
+ CRLissuer = NULL;
+ break;
+ }
+ if (gennames_allowed(dp->CRLissuer, only_DN) && CRLissuer == NULL)
+ /* don't break because any dp->distpoint in list is preferred */
+ CRLissuer = dp->CRLissuer;
+ }
+ } else {
+ if (crl == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ idp = X509_CRL_get_ext_d2i(crl,
+ NID_issuing_distribution_point, NULL, NULL);
+ if (idp != NULL && idp->distpoint != NULL)
+ dpn = idp->distpoint;
+ }
+
+ if (dpn == NULL && CRLissuer == NULL) {
+ if (cert != NULL) {
+ akid = X509_get_ext_d2i(cert, NID_akid, NULL, NULL);
+ if (akid != NULL && gennames_allowed(akid->issuer, only_DN))
+ CRLissuer = akid->issuer;
+ else
+ CRLissuer = issuers = gennames_new(X509_get_issuer_name(cert));
+ }
+ if (CRLissuer == NULL && crl != NULL) {
+ akid = X509_CRL_get_ext_d2i(crl, NID_akid, NULL, NULL);
+ if (akid != NULL && gennames_allowed(akid->issuer, only_DN))
+ CRLissuer = akid->issuer;
+ else
+ CRLissuer = issuers = gennames_new(X509_CRL_get_issuer(crl));
+ }
+ if (CRLissuer == NULL)
+ goto end;
+ }
+
+ status = OSSL_CMP_CRLSTATUS_new1(dpn, CRLissuer, last);
+ end:
+ sk_DIST_POINT_pop_free(crldps, DIST_POINT_free);
+ ISSUING_DIST_POINT_free(idp);
+ AUTHORITY_KEYID_free(akid);
+ sk_GENERAL_NAME_pop_free(issuers, GENERAL_NAME_free);
+ return status;
+}
+
+int OSSL_CMP_CRLSTATUS_get0(const OSSL_CMP_CRLSTATUS *crlstatus,
+ DIST_POINT_NAME **dpn, GENERAL_NAMES **issuer,
+ ASN1_TIME **thisUpdate)
+{
+ OSSL_CMP_CRLSOURCE *crlsource;
+
+ if (crlstatus == NULL || dpn == NULL || issuer == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ if ((crlsource = crlstatus->source) == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+
+ if (crlsource->type == OSSL_CMP_CRLSOURCE_DPN) {
+ *dpn = crlsource->value.dpn;
+ *issuer = NULL;
+ } else if (crlsource->type == OSSL_CMP_CRLSOURCE_ISSUER) {
+ *dpn = NULL;
+ *issuer = crlsource->value.issuer;
+ } else {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ if (thisUpdate != NULL)
+ *thisUpdate = crlstatus->thisUpdate;
+ return 1;
+}
+
+OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_crls(const X509_CRL *crl)
+{
+ OSSL_CMP_ITAV *itav;
+ X509_CRL *crl_copy = NULL;
+ STACK_OF(X509_CRL) *crls = NULL;
+
+ if ((itav = OSSL_CMP_ITAV_new()) == NULL)
+ return NULL;
+
+ if (crl != NULL) {
+ if ((crls = sk_X509_CRL_new_reserve(NULL, 1)) == NULL
+ || (crl_copy = X509_CRL_dup(crl)) == NULL
+ || !sk_X509_CRL_push(crls, crl_copy))
+ goto err;
+ crl_copy = NULL; /* ownership transferred to crls */
+ }
+
+ itav->infoType = OBJ_nid2obj(NID_id_it_crls);
+ itav->infoValue.crls = crls;
+ return itav;
+
+ err:
+ OPENSSL_free(crl_copy);
+ sk_X509_CRL_free(crls);
+ OSSL_CMP_ITAV_free(itav);
+ return NULL;
+}
+
+int OSSL_CMP_ITAV_get0_crls(const OSSL_CMP_ITAV *itav, STACK_OF(X509_CRL) **out)
+{
+ if (itav == NULL || out == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (OBJ_obj2nid(itav->infoType) != NID_id_it_crls) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT);
+ return 0;
+ }
+ *out = itav->infoValue.crls;
+ return 1;
+}
+
/* get ASN.1 encoded integer, return -2 on error; -1 is valid for certReqId */
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
{
@@ -209,7 +849,7 @@ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a)
}
static int ossl_cmp_msg_cb(int operation, ASN1_VALUE **pval,
- const ASN1_ITEM *it, void *exarg)
+ ossl_unused const ASN1_ITEM *it, void *exarg)
{
OSSL_CMP_MSG *msg = (OSSL_CMP_MSG *)*pval;
@@ -251,35 +891,31 @@ 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)
-
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)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTIFIEDKEYPAIR)
-
ASN1_SEQUENCE(OSSL_CMP_REVDETAILS) = {
ASN1_SIMPLE(OSSL_CMP_REVDETAILS, certDetails, OSSL_CRMF_CERTTEMPLATE),
ASN1_OPT(OSSL_CMP_REVDETAILS, crlEntryDetails, X509_EXTENSIONS)
} ASN1_SEQUENCE_END(OSSL_CMP_REVDETAILS)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVDETAILS)
-
ASN1_ITEM_TEMPLATE(OSSL_CMP_REVREQCONTENT) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, OSSL_CMP_REVREQCONTENT,
OSSL_CMP_REVDETAILS)
ASN1_ITEM_TEMPLATE_END(OSSL_CMP_REVREQCONTENT)
-
ASN1_SEQUENCE(OSSL_CMP_REVREPCONTENT) = {
ASN1_SEQUENCE_OF(OSSL_CMP_REVREPCONTENT, status, OSSL_CMP_PKISI),
ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_REVREPCONTENT, revCerts, OSSL_CRMF_CERTID,
@@ -288,7 +924,6 @@ ASN1_SEQUENCE(OSSL_CMP_REVREPCONTENT) = {
} ASN1_SEQUENCE_END(OSSL_CMP_REVREPCONTENT)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_REVREPCONTENT)
-
ASN1_SEQUENCE(OSSL_CMP_KEYRECREPCONTENT) = {
ASN1_SIMPLE(OSSL_CMP_KEYRECREPCONTENT, status, OSSL_CMP_PKISI),
ASN1_EXP_OPT(OSSL_CMP_KEYRECREPCONTENT, newSigCert, X509, 0),
@@ -298,21 +933,15 @@ ASN1_SEQUENCE(OSSL_CMP_KEYRECREPCONTENT) = {
} ASN1_SEQUENCE_END(OSSL_CMP_KEYRECREPCONTENT)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_KEYRECREPCONTENT)
-
ASN1_ITEM_TEMPLATE(OSSL_CMP_PKISTATUS) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_UNIVERSAL, 0, status, ASN1_INTEGER)
ASN1_ITEM_TEMPLATE_END(OSSL_CMP_PKISTATUS)
ASN1_SEQUENCE(OSSL_CMP_PKISI) = {
ASN1_SIMPLE(OSSL_CMP_PKISI, status, OSSL_CMP_PKISTATUS),
- /*
- * CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
- * so it is used directly
- */
+ /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */
ASN1_SEQUENCE_OF_OPT(OSSL_CMP_PKISI, statusString, ASN1_UTF8STRING),
- /*
- * OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING so used directly
- */
+ /* OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING, used directly */
ASN1_OPT(OSSL_CMP_PKISI, failInfo, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END(OSSL_CMP_PKISI)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
@@ -321,7 +950,8 @@ IMPLEMENT_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI)
ASN1_SEQUENCE(OSSL_CMP_CERTSTATUS) = {
ASN1_SIMPLE(OSSL_CMP_CERTSTATUS, certHash, ASN1_OCTET_STRING),
ASN1_SIMPLE(OSSL_CMP_CERTSTATUS, certReqId, ASN1_INTEGER),
- ASN1_OPT(OSSL_CMP_CERTSTATUS, statusInfo, OSSL_CMP_PKISI)
+ ASN1_OPT(OSSL_CMP_CERTSTATUS, statusInfo, OSSL_CMP_PKISI),
+ ASN1_EXP_OPT(OSSL_CMP_CERTSTATUS, hashAlg, X509_ALGOR, 0)
} ASN1_SEQUENCE_END(OSSL_CMP_CERTSTATUS)
IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS)
@@ -428,10 +1058,7 @@ ASN1_SEQUENCE(OSSL_CMP_PKIHEADER) = {
ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, transactionID, ASN1_OCTET_STRING, 4),
ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, senderNonce, ASN1_OCTET_STRING, 5),
ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, recipNonce, ASN1_OCTET_STRING, 6),
- /*
- * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING
- * so it is used directly
- */
+ /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */
ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, freeText, ASN1_UTF8STRING, 7),
ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, generalInfo,
OSSL_CMP_ITAV, 8)
diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c
index 4c8dbfdcd739..e129705e0e63 100644
--- a/crypto/cmp/cmp_client.c
+++ b/crypto/cmp/cmp_client.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -11,7 +11,6 @@
#include "cmp_local.h"
#include "internal/cryptlib.h"
-#include "e_os.h" /* ossl_sleep() */
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/bio.h>
@@ -32,7 +31,7 @@
static int unprotected_exception(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *rep,
int invalid_protection,
- int expected_type /* ignored here */)
+ ossl_unused int expected_type)
{
int rcvd_type = OSSL_CMP_MSG_get_bodytype(rep /* may be NULL */);
const char *msg_type = NULL;
@@ -117,6 +116,23 @@ static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
return 1;
}
+static int is_crep_with_waiting(const OSSL_CMP_MSG *resp, int rid)
+{
+ OSSL_CMP_CERTREPMESSAGE *crepmsg;
+ OSSL_CMP_CERTRESPONSE *crep;
+ int bt = OSSL_CMP_MSG_get_bodytype(resp);
+
+ if (!IS_CREP(bt))
+ return 0;
+
+ crepmsg = resp->body->value.ip; /* same for cp and kup */
+ crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
+
+ return (crep != NULL
+ && ossl_cmp_pkisi_get_status(crep->status)
+ == OSSL_CMP_PKISTATUS_waiting);
+}
+
/*-
* Perform the generic aspects of sending a request and receiving a response.
* Returns 1 on success and provides the received PKIMESSAGE in *rep.
@@ -138,8 +154,10 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
int time_left;
OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb;
+#ifndef OPENSSL_NO_HTTP
if (transfer_cb == NULL)
transfer_cb = OSSL_CMP_MSG_http_perform;
+#endif
*rep = NULL;
if (ctx->total_timeout != 0 /* not waiting indefinitely */) {
@@ -162,7 +180,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
/* should print error queue since transfer_cb may call ERR_clear_error() */
OSSL_CMP_CTX_print_errors(ctx);
- ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
+ if (ctx->server != NULL)
+ ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
*rep = (*transfer_cb)(ctx, req);
ctx->msg_timeout = bak_msg_timeout;
@@ -182,7 +201,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
* Still we use this preliminary value already for a progress report because
* the following msg verification may also produce log entries and may fail.
*/
- ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt));
+ ossl_cmp_log2(INFO, ctx, "received %s%s", ossl_cmp_bodytype_to_string(bt),
+ ossl_cmp_is_error_with_waiting(*rep) ? " (waiting)" : "");
/* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */
if (bt != OSSL_CMP_PKIBODY_POLLREP && bt != OSSL_CMP_PKIBODY_PKICONF
@@ -193,9 +213,17 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
expected_type))
return 0;
+ /*
+ * rep can have the expected response type, which during polling is pollRep.
+ * When polling, also any other non-error response (the final response)
+ * is fine here. When not yet polling, delayed delivery may be initiated
+ * by the server returning an error message with 'waiting' status (or a
+ * response message of expected type ip/cp/kup with 'waiting' status).
+ */
if (bt == expected_type
- /* as an answer to polling, there could be IP/CP/KUP: */
- || (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP))
+ || (expected_type == OSSL_CMP_PKIBODY_POLLREP
+ ? bt != OSSL_CMP_PKIBODY_ERROR
+ : ossl_cmp_is_error_with_waiting(*rep)))
return 1;
/* received message type is not one of the expected ones (e.g., error) */
@@ -237,7 +265,7 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
/*-
* When a 'waiting' PKIStatus has been received, this function is used to
- * poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup.
+ * poll, which should yield a pollRep or the final response.
* On receiving a pollRep, which includes a checkAfter value, it return this
* value if sleep == 0, else it sleeps as long as indicated and retries.
*
@@ -248,7 +276,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
* Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
* Returns 1 on success and provides the received PKIMESSAGE in *rep.
* In this case the caller is responsible for freeing *rep.
- * Returns 0 on error (which includes the case that timeout has been reached).
+ * Returns 0 on error (which includes the cases that timeout has been reached
+ * or a response with 'waiting' status has been received).
*/
static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
OSSL_CMP_MSG **rep, int *checkAfter)
@@ -314,7 +343,7 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
str, check_after);
if (ctx->total_timeout != 0) { /* timeout is not infinite */
- const int exp = 5; /* expected max time per msg round trip */
+ const int exp = OSSL_CMP_EXPECTED_RESP_TIME;
int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL));
if (time_left <= 0) {
@@ -331,15 +360,25 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
OSSL_CMP_MSG_free(prep);
prep = NULL;
if (sleep) {
- ossl_sleep((unsigned long)(1000 * check_after));
+ OSSL_sleep((unsigned long)(1000 * check_after));
} else {
if (checkAfter != NULL)
*checkAfter = (int)check_after;
return -1; /* exits the loop */
}
+ } else if (is_crep_with_waiting(prep, rid)
+ || ossl_cmp_is_error_with_waiting(prep)) {
+ /* received status must not be 'waiting' */
+ (void)ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
+ OSSL_CMP_CTX_FAILINFO_badRequest,
+ "polling already started",
+ 0 /* errorCode */, NULL);
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS);
+ goto err;
} else {
- ossl_cmp_info(ctx, "received ip/cp/kup after polling");
- /* any other body type has been rejected by send_receive_check() */
+ ossl_cmp_info(ctx, "received final response after polling");
+ if (!ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL))
+ return 0;
break;
}
}
@@ -351,11 +390,63 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
return 1;
err:
+ (void)ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL);
OSSL_CMP_MSG_free(preq);
OSSL_CMP_MSG_free(prep);
return 0;
}
+static int save_senderNonce_if_waiting(OSSL_CMP_CTX *ctx,
+ const OSSL_CMP_MSG *rep, int rid)
+{
+ /*
+ * Lightweight CMP Profile section 4.4 states: the senderNonce of the
+ * preceding request message because this value will be needed for checking
+ * the recipNonce of the final response to be received after polling.
+ */
+ if ((is_crep_with_waiting(rep, rid)
+ || ossl_cmp_is_error_with_waiting(rep))
+ && !ossl_cmp_ctx_set1_first_senderNonce(ctx, ctx->senderNonce))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Send request and get response possibly with polling initiated by error msg.
+ * Polling for ip/cp/kup/ with 'waiting' status is handled by cert_response().
+ */
+static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
+ OSSL_CMP_MSG **rep, int expected_type)
+{
+
+ if (!send_receive_check(ctx, req, rep, expected_type))
+ return 0;
+
+ if (ossl_cmp_is_error_with_waiting(*rep)) {
+ if (!save_senderNonce_if_waiting(ctx, *rep, OSSL_CMP_CERTREQID_NONE))
+ return 0;
+ /* not modifying ctx->status during certConf and error exchanges */
+ if (expected_type != OSSL_CMP_PKIBODY_PKICONF
+ && !save_statusInfo(ctx, (*rep)->body->value.error->pKIStatusInfo))
+ return 0;
+
+ OSSL_CMP_MSG_free(*rep);
+ *rep = NULL;
+
+ if (poll_for_response(ctx, 1 /* can sleep */, OSSL_CMP_CERTREQID_NONE,
+ rep, NULL /* checkAfter */) <= 0) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED);
+ return 0;
+ }
+ }
+ if (OSSL_CMP_MSG_get_bodytype(*rep) != expected_type) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return 0;
+ }
+
+ return 1;
+}
/*
* Send certConf for IR, CR or KUR sequences and check response,
* not modifying ctx->status during the certConf exchange
@@ -372,7 +463,8 @@ int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId,
if (certConf == NULL)
goto err;
- res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+ res = send_receive_also_delayed(ctx, certConf, &PKIconf,
+ OSSL_CMP_PKIBODY_PKICONF);
err:
OSSL_CMP_MSG_free(certConf);
@@ -396,7 +488,8 @@ int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL)
goto err;
- res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
+ res = send_receive_also_delayed(ctx, error,
+ &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
err:
OSSL_CMP_MSG_free(error);
@@ -490,6 +583,7 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
{
X509_STORE *out_trusted = OSSL_CMP_CTX_get_certConf_cb_arg(ctx);
STACK_OF(X509) *chain = NULL;
+
(void)text; /* make (artificial) use of var to prevent compiler warning */
if (fail_info != 0) /* accept any error flagged by CMP core library */
@@ -516,7 +610,7 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
if (X509_verify_cert(csc) <= 0)
goto err;
- if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc),
+ if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc),
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
| X509_ADD_FLAG_NO_SS)) {
sk_X509_free(chain);
@@ -544,7 +638,7 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
"success building approximate chain for newly enrolled cert");
}
(void)ossl_cmp_ctx_set1_newChain(ctx, chain);
- sk_X509_pop_free(chain, X509_free);
+ OSSL_STACK_OF_X509_free(chain);
return fail_info;
}
@@ -559,70 +653,104 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
*/
static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
OSSL_CMP_MSG **resp, int *checkAfter,
- int req_type, int expected_type)
+ 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;
- OSSL_CMP_CERTRESPONSE *crep;
+ OSSL_CMP_CERTREPMESSAGE *crepmsg = NULL;
+ OSSL_CMP_CERTRESPONSE *crep = NULL;
OSSL_CMP_certConf_cb_t cb;
X509 *cert;
char *subj = NULL;
int ret = 1;
+ int rcvd_type;
+ OSSL_CMP_PKISI *si;
if (!ossl_assert(ctx != NULL))
return 0;
retry:
- crepmsg = (*resp)->body->value.ip; /* same for cp and kup */
- if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) {
- ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
- return 0;
- }
- crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
- if (crep == NULL)
- return 0;
- if (!save_statusInfo(ctx, crep->status))
- return 0;
- if (rid == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */
- rid = ossl_cmp_asn1_get_int(crep->certReqId);
- if (rid < OSSL_CMP_CERTREQID_NONE) {
- ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ rcvd_type = OSSL_CMP_MSG_get_bodytype(*resp);
+ if (IS_CREP(rcvd_type)) {
+ crepmsg = (*resp)->body->value.ip; /* same for cp and kup */
+ if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
return 0;
}
+ crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
+ if (crep == NULL)
+ return 0;
+ si = crep->status;
+
+ if (rid == OSSL_CMP_CERTREQID_NONE) {
+ /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */
+ rid = ossl_cmp_asn1_get_int(crep->certReqId);
+ if (rid < OSSL_CMP_CERTREQID_NONE) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
+ return 0;
+ }
+ }
+ } else if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) {
+ si = (*resp)->body->value.error->pKIStatusInfo;
+ } else {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return 0;
}
- if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) {
+ if (!save_statusInfo(ctx, si))
+ return 0;
+
+ if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting) {
+ /*
+ * Here we allow both and error message with waiting indication
+ * as well as a certificate response with waiting indication, where
+ * its flavor (ip, cp, or kup) may not strictly match ir/cr/p10cr/kur.
+ */
OSSL_CMP_MSG_free(*resp);
*resp = NULL;
if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) {
if (ret == -1) /* at this point implies sleep == 0 */
return ret; /* waiting */
- goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */
+ goto retry; /* got some response other than pollRep */
} else {
ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED);
return 0;
}
}
+ /* at this point, we have received ip/cp/kup/error without waiting */
+ if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_RECEIVED_ERROR);
+ return 0;
+ }
+ /* here we are strict on the flavor of ip/cp/kup: must match request */
+ if (rcvd_type != expected_type) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return 0;
+ }
+
cert = get1_cert_status(ctx, (*resp)->body->type, crep);
if (cert == NULL) {
ERR_add_error_data(1, "; cannot extract certificate from response");
return 0;
}
- if (!ossl_cmp_ctx_set0_newCert(ctx, cert))
+ if (!ossl_cmp_ctx_set0_newCert(ctx, cert)) {
+ X509_free(cert);
return 0;
+ }
/*
* if the CMP server returned certificates in the caPubs field, copy them
* to the context so that they can be retrieved if necessary
*/
- if (crepmsg->caPubs != NULL
+ if (crepmsg != NULL && crepmsg->caPubs != NULL
&& !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs))
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))) {
@@ -649,6 +777,10 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
if (fail_info != 0) /* immediately log error before any certConf exchange */
ossl_cmp_log1(ERROR, ctx,
"rejecting newly enrolled cert with subject: %s", subj);
+ /*
+ * certConf exchange should better be moved to do_certreq_seq() such that
+ * also more low-level errors with CertReqMessages get reported to server
+ */
if (!ctx->disableConfirm
&& !ossl_cmp_hdr_has_implicitConfirm((*resp)->header)) {
if (!ossl_cmp_exchange_certConf(ctx, rid, fail_info, txt))
@@ -705,6 +837,9 @@ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */
if (!initial_certreq(ctx, req_type, crm, &rep, rep_type))
goto err;
+
+ if (!save_senderNonce_if_waiting(ctx, rep, rid))
+ return 0;
} else {
if (req_type < 0)
return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
@@ -732,7 +867,6 @@ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type,
X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
const OSSL_CRMF_MSG *crm)
{
-
OSSL_CMP_MSG *rep = NULL;
int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR;
int rid = is_p10 ? OSSL_CMP_CERTREQID_NONE : OSSL_CMP_CERTREQID;
@@ -747,6 +881,9 @@ X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type,
if (!initial_certreq(ctx, req_type, crm, &rep, rep_type))
goto err;
+ if (!save_senderNonce_if_waiting(ctx, rep, rid))
+ return 0;
+
if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type)
<= 0)
goto err;
@@ -773,7 +910,8 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
return 0;
}
ctx->status = OSSL_CMP_PKISTATUS_request;
- if (ctx->oldCert == NULL && ctx->p10CSR == NULL) {
+ if (ctx->oldCert == NULL && ctx->p10CSR == NULL
+ && (ctx->serialNumber == NULL || ctx->issuer == NULL)) {
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_REFERENCE_CERT);
return 0;
}
@@ -783,7 +921,7 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
goto end;
ctx->status = OSSL_CMP_PKISTATUS_trans;
- if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
+ if (!send_receive_also_delayed(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
goto end;
rrep = rp->body->value.rp;
@@ -840,7 +978,8 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
OSSL_CRMF_CERTTEMPLATE *tmpl =
sk_OSSL_CMP_REVDETAILS_value(rr->body->value.rr, rsid)->certDetails;
const X509_NAME *issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
- const ASN1_INTEGER *serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
+ const ASN1_INTEGER *serial =
+ OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) != num_RevDetails) {
ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_RP_COMPONENT_COUNT);
@@ -903,7 +1042,7 @@ STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx)
goto err;
ctx->status = OSSL_CMP_PKISTATUS_trans;
- if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
+ if (!send_receive_also_delayed(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
goto err;
ctx->status = OSSL_CMP_PKISTATUS_accepted;
diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c
index 9d9bd357daf7..7b78ab16036b 100644
--- a/crypto/cmp/cmp_ctx.c
+++ b/crypto/cmp/cmp_ctx.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -20,16 +20,35 @@
#include <openssl/crmf.h>
#include <openssl/err.h>
+#define DEFINE_OSSL_CMP_CTX_get0(FIELD, TYPE) \
+ DEFINE_OSSL_CMP_CTX_get0_NAME(FIELD, FIELD, TYPE)
+#define DEFINE_OSSL_CMP_CTX_get0_NAME(NAME, FIELD, TYPE) \
+TYPE *OSSL_CMP_CTX_get0_##NAME(const OSSL_CMP_CTX *ctx) \
+{ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return NULL; \
+ } \
+ return ctx->FIELD; \
+}
+
/*
* Get current certificate store containing trusted root CA certs
*/
-X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return ctx->trusted;
+DEFINE_OSSL_CMP_CTX_get0_NAME(trusted, trusted, X509_STORE)
+
+#define DEFINE_OSSL_set0(PREFIX, FIELD, TYPE) \
+ DEFINE_OSSL_set0_NAME(PREFIX, FIELD, FIELD, TYPE)
+#define DEFINE_OSSL_set0_NAME(PREFIX, NAME, FIELD, TYPE) \
+int PREFIX##_set0##_##NAME(OSSL_CMP_CTX *ctx, TYPE *val) \
+{ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return 0; \
+ } \
+ TYPE##_free(ctx->FIELD); \
+ ctx->FIELD = val; \
+ return 1; \
}
/*
@@ -37,26 +56,13 @@ X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
* and a cert verification callback function used for CMP server authentication.
* Any already existing store entry is freed. Given NULL, the entry is reset.
*/
-int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- X509_STORE_free(ctx->trusted);
- ctx->trusted = store;
- return 1;
-}
+DEFINE_OSSL_set0_NAME(OSSL_CMP_CTX, trusted, trusted, X509_STORE)
+
+DEFINE_OSSL_CMP_CTX_get0(libctx, OSSL_LIB_CTX)
+DEFINE_OSSL_CMP_CTX_get0(propq, const char)
/* Get current list of non-trusted intermediate certs */
-STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return ctx->untrusted;
-}
+DEFINE_OSSL_CMP_CTX_get0(untrusted, STACK_OF(X509))
/*
* Set untrusted certificates for path construction in authentication of
@@ -73,11 +79,11 @@ int OSSL_CMP_CTX_set1_untrusted(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
if (!ossl_x509_add_certs_new(&untrusted, certs,
X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
goto err;
- sk_X509_pop_free(ctx->untrusted, X509_free);
+ OSSL_STACK_OF_X509_free(ctx->untrusted);
ctx->untrusted = untrusted;
return 1;
err:
- sk_X509_pop_free(untrusted, X509_free);
+ OSSL_STACK_OF_X509_free(untrusted);
return 0;
}
@@ -108,7 +114,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
ctx->libctx = libctx;
if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)
- goto oom;
+ goto err;
ctx->log_verbosity = OSSL_CMP_LOG_INFO;
@@ -117,9 +123,12 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
ctx->keep_alive = 1;
ctx->msg_timeout = -1;
+ ctx->tls_used = -1; /* default for backward compatibility */
- if ((ctx->untrusted = sk_X509_new_null()) == NULL)
- goto oom;
+ if ((ctx->untrusted = sk_X509_new_null()) == NULL) {
+ ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
+ goto err;
+ }
ctx->pbm_slen = 16;
if (!cmp_ctx_set_md(ctx, &ctx->pbm_owf, NID_sha256))
@@ -135,8 +144,6 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
- oom:
- ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
err:
OSSL_CMP_CTX_free(ctx);
return NULL;
@@ -157,11 +164,13 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
return 0;
}
+#ifndef OPENSSL_NO_HTTP
if (ctx->http_ctx != NULL) {
(void)OSSL_HTTP_close(ctx->http_ctx, 1);
ossl_cmp_debug(ctx, "disconnected from CMP server");
ctx->http_ctx = NULL;
}
+#endif
ctx->status = OSSL_CMP_PKISTATUS_unspecified;
ctx->failInfoCode = -1;
@@ -173,7 +182,8 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
&& ossl_cmp_ctx_set1_newChain(ctx, NULL)
&& ossl_cmp_ctx_set1_caPubs(ctx, NULL)
&& ossl_cmp_ctx_set1_extraCertsIn(ctx, NULL)
- && ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL)
+ && ossl_cmp_ctx_set1_validatedSrvCert(ctx, NULL)
+ && ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL)
&& OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
&& OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)
&& ossl_cmp_ctx_set1_recipNonce(ctx, NULL);
@@ -185,10 +195,12 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
if (ctx == NULL)
return;
+#ifndef OPENSSL_NO_HTTP
if (ctx->http_ctx != NULL) {
(void)OSSL_HTTP_close(ctx->http_ctx, 1);
ossl_cmp_debug(ctx, "disconnected from CMP server");
}
+#endif
OPENSSL_free(ctx->propq);
OPENSSL_free(ctx->serverPath);
OPENSSL_free(ctx->server);
@@ -199,10 +211,10 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
X509_free(ctx->validatedSrvCert);
X509_NAME_free(ctx->expected_sender);
X509_STORE_free(ctx->trusted);
- sk_X509_pop_free(ctx->untrusted, X509_free);
+ OSSL_STACK_OF_X509_free(ctx->untrusted);
X509_free(ctx->cert);
- sk_X509_pop_free(ctx->chain, X509_free);
+ OSSL_STACK_OF_X509_free(ctx->chain);
EVP_PKEY_free(ctx->pkey);
ASN1_OCTET_STRING_free(ctx->referenceValue);
if (ctx->secretValue != NULL)
@@ -215,120 +227,83 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
ASN1_OCTET_STRING_free(ctx->transactionID);
ASN1_OCTET_STRING_free(ctx->senderNonce);
ASN1_OCTET_STRING_free(ctx->recipNonce);
- sk_OSSL_CMP_ITAV_pop_free(ctx->geninfo_ITAVs, OSSL_CMP_ITAV_free);
- sk_X509_pop_free(ctx->extraCertsOut, X509_free);
+ ASN1_OCTET_STRING_free(ctx->first_senderNonce);
+ OSSL_CMP_ITAVs_free(ctx->geninfo_ITAVs);
+ OSSL_STACK_OF_X509_free(ctx->extraCertsOut);
EVP_PKEY_free(ctx->newPkey);
X509_NAME_free(ctx->issuer);
+ ASN1_INTEGER_free(ctx->serialNumber);
X509_NAME_free(ctx->subjectName);
sk_GENERAL_NAME_pop_free(ctx->subjectAltNames, GENERAL_NAME_free);
- sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
+ X509_EXTENSIONS_free(ctx->reqExtensions);
sk_POLICYINFO_pop_free(ctx->policies, POLICYINFO_free);
X509_free(ctx->oldCert);
X509_REQ_free(ctx->p10CSR);
- sk_OSSL_CMP_ITAV_pop_free(ctx->genm_ITAVs, OSSL_CMP_ITAV_free);
+ OSSL_CMP_ITAVs_free(ctx->genm_ITAVs);
- sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
+ OSSL_CMP_PKIFREETEXT_free(ctx->statusString);
X509_free(ctx->newCert);
- sk_X509_pop_free(ctx->newChain, X509_free);
- sk_X509_pop_free(ctx->caPubs, X509_free);
- sk_X509_pop_free(ctx->extraCertsIn, X509_free);
+ OSSL_STACK_OF_X509_free(ctx->newChain);
+ OSSL_STACK_OF_X509_free(ctx->caPubs);
+ OSSL_STACK_OF_X509_free(ctx->extraCertsIn);
OPENSSL_free(ctx);
}
-int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
- ctx->status = status;
- return 1;
+#define DEFINE_OSSL_set(PREFIX, FIELD, TYPE) \
+int PREFIX##_set_##FIELD(OSSL_CMP_CTX *ctx, TYPE val) \
+{ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return 0; \
+ } \
+ ctx->FIELD = val; \
+ return 1; \
+}
+
+DEFINE_OSSL_set(ossl_cmp_ctx, status, int)
+
+#define DEFINE_OSSL_get(PREFIX, FIELD, TYPE, ERR_RET) \
+TYPE PREFIX##_get_##FIELD(const OSSL_CMP_CTX *ctx) \
+{ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return ERR_RET; \
+ } \
+ return ctx->FIELD; \
}
/*
* Returns the PKIStatus from the last CertRepMessage
* or Revocation Response or error message, -1 on error
*/
-int OSSL_CMP_CTX_get_status(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return -1;
- }
- return ctx->status;
-}
+DEFINE_OSSL_get(OSSL_CMP_CTX, status, int, -1)
/*
* Returns the statusString from the last CertRepMessage
* or Revocation Response or error message, NULL on error
*/
-OSSL_CMP_PKIFREETEXT *OSSL_CMP_CTX_get0_statusString(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return ctx->statusString;
-}
+DEFINE_OSSL_CMP_CTX_get0(statusString, OSSL_CMP_PKIFREETEXT)
-int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
- OSSL_CMP_PKIFREETEXT *text)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
- sk_ASN1_UTF8STRING_pop_free(ctx->statusString, ASN1_UTF8STRING_free);
- ctx->statusString = text;
- return 1;
-}
-
-int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
- X509_free(ctx->validatedSrvCert);
- ctx->validatedSrvCert = cert;
- return 1;
-}
+DEFINE_OSSL_set0(ossl_cmp_ctx, statusString, OSSL_CMP_PKIFREETEXT)
/* Set callback function for checking if the cert is ok or should be rejected */
-int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- ctx->certConf_cb = cb;
- return 1;
-}
+DEFINE_OSSL_set(OSSL_CMP_CTX, certConf_cb, OSSL_CMP_certConf_cb_t)
/*
* Set argument, respectively a pointer to a structure containing arguments,
* optionally to be used by the certConf callback.
*/
-int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- ctx->certConf_cb_arg = arg;
- return 1;
-}
+DEFINE_OSSL_set(OSSL_CMP_CTX, certConf_cb_arg, void *)
/*
* Get argument, respectively the pointer to a structure containing arguments,
* optionally to be used by certConf callback.
* Returns callback argument set previously (NULL if not set or on error)
*/
-void *OSSL_CMP_CTX_get_certConf_cb_arg(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return ctx->certConf_cb_arg;
-}
+DEFINE_OSSL_get(OSSL_CMP_CTX, certConf_cb_arg, void *, NULL)
#ifndef OPENSSL_NO_TRACE
static size_t ossl_cmp_log_trace_cb(const char *buf, size_t cnt,
@@ -452,8 +427,8 @@ int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
}
- return ossl_cmp_asn1_octet_string_set1_bytes(&ctx->referenceValue, ref,
- len);
+ return
+ ossl_cmp_asn1_octet_string_set1_bytes(&ctx->referenceValue, ref, len);
}
/* Set or clear the password to be used for protecting messages with PBMAC */
@@ -461,6 +436,7 @@ int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx,
const unsigned char *sec, int len)
{
ASN1_OCTET_STRING *secretValue = NULL;
+
if (ctx == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
@@ -475,74 +451,51 @@ int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx,
return 1;
}
+#define DEFINE_OSSL_CMP_CTX_get1_certs(FIELD) \
+STACK_OF(X509) *OSSL_CMP_CTX_get1_##FIELD(const OSSL_CMP_CTX *ctx) \
+{ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return NULL; \
+ } \
+ return X509_chain_up_ref(ctx->FIELD); \
+}
+
/* Returns the cert chain computed by OSSL_CMP_certConf_cb(), NULL on error */
-STACK_OF(X509) *OSSL_CMP_CTX_get1_newChain(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return X509_chain_up_ref(ctx->newChain);
+DEFINE_OSSL_CMP_CTX_get1_certs(newChain)
+
+#define DEFINE_OSSL_set1_certs(PREFIX, FIELD) \
+int PREFIX##_set1_##FIELD(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs) \
+{ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return 0; \
+ } \
+ OSSL_STACK_OF_X509_free(ctx->FIELD); \
+ ctx->FIELD = NULL; \
+ return certs == NULL || (ctx->FIELD = X509_chain_up_ref(certs)) != NULL; \
}
/*
* Copies any given stack of inbound X509 certificates to newChain
* of the OSSL_CMP_CTX structure so that they may be retrieved later.
*/
-int ossl_cmp_ctx_set1_newChain(OSSL_CMP_CTX *ctx, STACK_OF(X509) *newChain)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
-
- sk_X509_pop_free(ctx->newChain, X509_free);
- ctx->newChain = NULL;
- return newChain == NULL ||
- (ctx->newChain = X509_chain_up_ref(newChain)) != NULL;
-}
+DEFINE_OSSL_set1_certs(ossl_cmp_ctx, newChain)
/* Returns the stack of extraCerts received in CertRepMessage, NULL on error */
-STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return X509_chain_up_ref(ctx->extraCertsIn);
-}
+DEFINE_OSSL_CMP_CTX_get1_certs(extraCertsIn)
/*
* Copies any given stack of inbound X509 certificates to extraCertsIn
* of the OSSL_CMP_CTX structure so that they may be retrieved later.
*/
-int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
- STACK_OF(X509) *extraCertsIn)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
-
- sk_X509_pop_free(ctx->extraCertsIn, X509_free);
- ctx->extraCertsIn = NULL;
- return extraCertsIn == NULL
- || (ctx->extraCertsIn = X509_chain_up_ref(extraCertsIn)) != NULL;
-}
+DEFINE_OSSL_set1_certs(ossl_cmp_ctx, extraCertsIn)
/*
* Copies any given stack as the new stack of X509
* certificates to send out in the extraCerts field.
*/
-int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
- STACK_OF(X509) *extraCertsOut)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
-
- sk_X509_pop_free(ctx->extraCertsOut, X509_free);
- ctx->extraCertsOut = NULL;
- return extraCertsOut == NULL
- || (ctx->extraCertsOut = X509_chain_up_ref(extraCertsOut)) != NULL;
-}
+DEFINE_OSSL_set1_certs(OSSL_CMP_CTX, extraCertsOut)
/*
* Add the given policy info object
@@ -583,6 +536,8 @@ int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx)
return 1;
}
+DEFINE_OSSL_CMP_CTX_get0(geninfo_ITAVs, STACK_OF(OSSL_CMP_ITAV))
+
/* Add an itav for the body of outgoing general messages */
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
{
@@ -598,28 +553,13 @@ int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
* were received in the caPubs field of the last CertRepMessage.
* Returns NULL on error
*/
-STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return X509_chain_up_ref(ctx->caPubs);
-}
+DEFINE_OSSL_CMP_CTX_get1_certs(caPubs)
/*
* Copies any given stack of certificates to the given
* OSSL_CMP_CTX structure so that they may be retrieved later.
*/
-int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
-
- sk_X509_pop_free(ctx->caPubs, X509_free);
- ctx->caPubs = NULL;
- return caPubs == NULL || (ctx->caPubs = X509_chain_up_ref(caPubs)) != NULL;
-}
+DEFINE_OSSL_set1_certs(ossl_cmp_ctx, caPubs)
#define char_dup OPENSSL_strdup
#define char_free OPENSSL_free
@@ -642,8 +582,9 @@ int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, const TYPE *val) \
#define X509_invalid(cert) (!ossl_x509v3_cache_extensions(cert))
#define EVP_PKEY_invalid(key) 0
-#define DEFINE_OSSL_CMP_CTX_set1_up_ref(FIELD, TYPE) \
-int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
+
+#define DEFINE_OSSL_set1_up_ref(PREFIX, FIELD, TYPE) \
+int PREFIX##_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
{ \
if (ctx == NULL) { \
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
@@ -662,12 +603,14 @@ int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
return 1; \
}
+DEFINE_OSSL_set1_up_ref(ossl_cmp_ctx, validatedSrvCert, X509)
+
/*
* Pins the server certificate to be directly trusted (even if it is expired)
* for verifying response messages.
* Cert pointer is not consumed. It may be NULL to clear the entry.
*/
-DEFINE_OSSL_CMP_CTX_set1_up_ref(srvCert, X509)
+DEFINE_OSSL_set1_up_ref(OSSL_CMP_CTX, srvCert, X509)
/* Set the X509 name of the recipient to be placed in the PKIHeader */
DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME)
@@ -678,6 +621,8 @@ DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME)
/* Set the X509 name of the issuer to be placed in the certTemplate */
DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME)
+/* Set the ASN1_INTEGER serial to be placed in the certTemplate for rr */
+DEFINE_OSSL_CMP_CTX_set1(serialNumber, ASN1_INTEGER)
/*
* Set the subject name that will be placed in the certificate
* request. This will be the subject name on the received certificate.
@@ -697,7 +642,7 @@ int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts)
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_SAN_SOURCES);
return 0;
}
- sk_X509_EXTENSION_pop_free(ctx->reqExtensions, X509_EXTENSION_free);
+ X509_EXTENSIONS_free(ctx->reqExtensions);
ctx->reqExtensions = exts;
return 1;
}
@@ -750,7 +695,7 @@ int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
* Set our own client certificate, used for example in KUR and when
* doing the IR with existing certificate.
*/
-DEFINE_OSSL_CMP_CTX_set1_up_ref(cert, X509)
+DEFINE_OSSL_set1_up_ref(OSSL_CMP_CTX, cert, X509)
int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted,
STACK_OF(X509) *candidates)
@@ -784,7 +729,7 @@ int OSSL_CMP_CTX_build_cert_chain(OSSL_CMP_CTX *ctx, X509_STORE *own_trusted,
* Also used as reference cert (defaulting to cert) for deriving subject DN
* and SANs. Its issuer is used as default recipient in the CMP message header.
*/
-DEFINE_OSSL_CMP_CTX_set1_up_ref(oldCert, X509)
+DEFINE_OSSL_set1_up_ref(OSSL_CMP_CTX, oldCert, X509)
/* Set the PKCS#10 CSR to be sent in P10CR */
DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ)
@@ -793,31 +738,19 @@ DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ)
* Set the (newly received in IP/KUP/CP) certificate in the context.
* This only permits for one cert to be enrolled at a time.
*/
-int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
+DEFINE_OSSL_set0(ossl_cmp_ctx, newCert, X509)
- X509_free(ctx->newCert);
- ctx->newCert = cert;
- return 1;
-}
+/* Get successfully validated server cert, if any, of current transaction */
+DEFINE_OSSL_CMP_CTX_get0(validatedSrvCert, X509)
/*
* Get the (newly received in IP/KUP/CP) client certificate from the context
* This only permits for one client cert to be received...
*/
-X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return ctx->newCert;
-}
+DEFINE_OSSL_CMP_CTX_get0(newCert, X509)
/* Set the client's current private key */
-DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY)
+DEFINE_OSSL_set1_up_ref(OSSL_CMP_CTX, pkey, EVP_PKEY)
/* Set new key pair. Used e.g. when doing Key Update */
int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
@@ -864,151 +797,77 @@ EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx)
return ctx->pkey;
}
-/* Set the given transactionID to the context */
-int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
- const ASN1_OCTET_STRING *id)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- return ossl_cmp_asn1_octet_string_set1(&ctx->transactionID, id);
+#define DEFINE_set1_ASN1_OCTET_STRING(PREFIX, FIELD) \
+int PREFIX##_set1_##FIELD(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *id) \
+{ \
+ if (ctx == NULL) { \
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); \
+ return 0; \
+ } \
+ return ossl_cmp_asn1_octet_string_set1(&ctx->FIELD, id); \
}
+/* Set the given transactionID to the context */
+DEFINE_set1_ASN1_OCTET_STRING(OSSL_CMP_CTX, transactionID)
+
/* Set the nonce to be used for the recipNonce in the message created next */
-int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
- const ASN1_OCTET_STRING *nonce)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
- return ossl_cmp_asn1_octet_string_set1(&ctx->recipNonce, nonce);
-}
+DEFINE_set1_ASN1_OCTET_STRING(ossl_cmp_ctx, recipNonce)
/* Stores the given nonce as the last senderNonce sent out */
-int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
- const ASN1_OCTET_STRING *nonce)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- return ossl_cmp_asn1_octet_string_set1(&ctx->senderNonce, nonce);
-}
+DEFINE_set1_ASN1_OCTET_STRING(OSSL_CMP_CTX, senderNonce)
+
+/* store the first req sender nonce for verifying delayed delivery */
+DEFINE_set1_ASN1_OCTET_STRING(ossl_cmp_ctx, first_senderNonce)
/* Set the proxy server to use for HTTP(S) connections */
DEFINE_OSSL_CMP_CTX_set1(proxy, char)
-/* Set the (HTTP) host name of the CMP server */
+/* Set the (HTTP) hostname of the CMP server */
DEFINE_OSSL_CMP_CTX_set1(server, char)
/* Set the server exclusion list of the HTTP proxy server */
DEFINE_OSSL_CMP_CTX_set1(no_proxy, char)
+#ifndef OPENSSL_NO_HTTP
/* Set the http connect/disconnect callback function to be used for HTTP(S) */
-int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- ctx->http_cb = cb;
- return 1;
-}
+DEFINE_OSSL_set(OSSL_CMP_CTX, http_cb, OSSL_HTTP_bio_cb_t)
/* Set argument optionally to be used by the http connect/disconnect callback */
-int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- ctx->http_cb_arg = arg;
- return 1;
-}
+DEFINE_OSSL_set(OSSL_CMP_CTX, http_cb_arg, void *)
/*
* Get argument optionally to be used by the http connect/disconnect callback
* Returns callback argument set previously (NULL if not set or on error)
*/
-void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return ctx->http_cb_arg;
-}
+DEFINE_OSSL_get(OSSL_CMP_CTX, http_cb_arg, void *, NULL)
+#endif
/* Set callback function for sending CMP request and receiving response */
-int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- ctx->transfer_cb = cb;
- return 1;
-}
+DEFINE_OSSL_set(OSSL_CMP_CTX, transfer_cb, OSSL_CMP_transfer_cb_t)
/* Set argument optionally to be used by the transfer callback */
-int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- ctx->transfer_cb_arg = arg;
- return 1;
-}
+DEFINE_OSSL_set(OSSL_CMP_CTX, transfer_cb_arg, void *)
/*
* Get argument optionally to be used by the transfer callback.
* Returns callback argument set previously (NULL if not set or on error)
*/
-void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return NULL;
- }
- return ctx->transfer_cb_arg;
-}
+DEFINE_OSSL_get(OSSL_CMP_CTX, transfer_cb_arg, void *, NULL)
/** Set the HTTP server port to be used */
-int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return 0;
- }
- ctx->serverPort = port;
- return 1;
-}
+DEFINE_OSSL_set(OSSL_CMP_CTX, serverPort, int)
/* Set the HTTP path to be used on the server (e.g "pkix/") */
DEFINE_OSSL_CMP_CTX_set1(serverPath, char)
/* Set the failInfo error code as bit encoding in OSSL_CMP_CTX */
-int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info)
-{
- if (!ossl_assert(ctx != NULL))
- return 0;
- ctx->failInfoCode = fail_info;
- return 1;
-}
+DEFINE_OSSL_set(ossl_cmp_ctx, failInfoCode, int)
/*
* Get the failInfo error code in OSSL_CMP_CTX as bit encoding.
* Returns bit string as integer on success, -1 on error
*/
-int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx)
-{
- if (ctx == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
- return -1;
- }
- return ctx->failInfoCode;
-}
+DEFINE_OSSL_get(OSSL_CMP_CTX, failInfoCode, int, -1)
/* Set a Boolean or integer option of the context to the "val" arg */
int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
@@ -1056,6 +915,9 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
ctx->unprotectedErrors = val;
break;
+ case OSSL_CMP_OPT_NO_CACHE_EXTRACERTS:
+ ctx->noCacheExtraCerts = val;
+ break;
case OSSL_CMP_OPT_VALIDITY_DAYS:
ctx->days = val;
break;
@@ -1098,6 +960,9 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
case OSSL_CMP_OPT_TOTAL_TIMEOUT:
ctx->total_timeout = val;
break;
+ case OSSL_CMP_OPT_USE_TLS:
+ ctx->tls_used = val;
+ break;
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
ctx->permitTAInExtraCertsForIR = val;
break;
@@ -1138,6 +1003,8 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
return ctx->unprotectedSend;
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
return ctx->unprotectedErrors;
+ case OSSL_CMP_OPT_NO_CACHE_EXTRACERTS:
+ return ctx->noCacheExtraCerts;
case OSSL_CMP_OPT_VALIDITY_DAYS:
return ctx->days;
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
@@ -1162,6 +1029,8 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
return ctx->msg_timeout;
case OSSL_CMP_OPT_TOTAL_TIMEOUT:
return ctx->total_timeout;
+ case OSSL_CMP_OPT_USE_TLS:
+ return ctx->tls_used;
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
return ctx->permitTAInExtraCertsForIR;
case OSSL_CMP_OPT_REVOCATION_REASON:
diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c
index dfc6dfbedee9..6d87d7b463dd 100644
--- a/crypto/cmp/cmp_err.c
+++ b/crypto/cmp/cmp_err.c
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2025 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
@@ -76,16 +76,31 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"error validating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_SIGNATURE),
"error validating signature"},
+ {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),
"failure obtaining random"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAIL_INFO_OUT_OF_RANGE),
"fail info out of range"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GENERATE_CERTREQTEMPLATE),
+ "generate certreqtemplate"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GENERATE_CRLSTATUS),
+ "error creating crlstatus"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GETTING_GENP), "getting genp"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_GET_ITAV), "get itav"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ARGS), "invalid args"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_GENP), "invalid genp"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_KEYSPEC), "invalid keyspec"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_OPTION), "invalid option"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_INVALID_ROOTCAKEYUPDATE),
+ "invalid rootcakeyupdate"},
+ {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"},
@@ -139,18 +154,30 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSACTIONID_UNMATCHED),
"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),
+ "unexpected crlstatuslist"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
"unexpected pkistatus"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_POLLREQ), "unexpected pollreq"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_SENDER), "unexpected sender"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
"unknown algorithm id"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CRL_ISSUER), "unknown crl issuer"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_PKISTATUS), "unknown pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM),
"unsupported algorithm"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE),
"unsupported key type"},
+ {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PKIBODY),
+ "unsupported pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC),
"unsupported protection alg dhbasedmac"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_VALUE_TOO_LARGE), "value too large"},
diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c
index 8c553af61a53..d00c9f76bb42 100644
--- a/crypto/cmp/cmp_hdr.c
+++ b/crypto/cmp/cmp_hdr.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2024 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -72,6 +72,16 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr)
return hdr->recipNonce;
}
+STACK_OF(OSSL_CMP_ITAV)
+ *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr)
+{
+ if (hdr == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return NULL;
+ }
+ return hdr->generalInfo;
+}
+
/* a NULL-DN as an empty sequence of RDNs */
int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name)
{
@@ -79,34 +89,6 @@ int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name)
|| (name->type == GEN_DIRNAME && IS_NULL_DN(name->d.directoryName));
}
-/* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */
-static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src)
-{
- GENERAL_NAME *name;
-
- if (!ossl_assert(tgt != NULL))
- return 0;
- if ((name = GENERAL_NAME_new()) == NULL)
- goto err;
- name->type = GEN_DIRNAME;
-
- if (src == NULL) { /* NULL-DN */
- if ((name->d.directoryName = X509_NAME_new()) == NULL)
- goto err;
- } else if (!X509_NAME_set(&name->d.directoryName, src)) {
- goto err;
- }
-
- GENERAL_NAME_free(*tgt);
- *tgt = name;
-
- return 1;
-
- err:
- GENERAL_NAME_free(name);
- return 0;
-}
-
/*
* Set the sender name in PKIHeader.
* when nm is NULL, sender is set to an empty string
@@ -116,14 +98,14 @@ int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm)
{
if (!ossl_assert(hdr != NULL))
return 0;
- return set1_general_name(&hdr->sender, nm);
+ return GENERAL_NAME_set1_X509_NAME(&hdr->sender, nm);
}
int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm)
{
if (!ossl_assert(hdr != NULL))
return 0;
- return set1_general_name(&hdr->recipient, nm);
+ return GENERAL_NAME_set1_X509_NAME(&hdr->recipient, nm);
}
int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr)
@@ -276,8 +258,7 @@ int ossl_cmp_hdr_set_transactionID(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
if (!set_random(&ctx->transactionID, ctx,
OSSL_CMP_TRANSACTIONID_LENGTH))
return 0;
- tid = OPENSSL_buf2hexstr(ctx->transactionID->data,
- ctx->transactionID->length);
+ tid = i2s_ASN1_OCTET_STRING(NULL, ctx->transactionID);
if (tid != NULL)
ossl_cmp_log1(DEBUG, ctx,
"Starting new transaction with ID=%s", tid);
@@ -302,11 +283,12 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
return 0;
/*
- * If neither protection cert nor oldCert nor subject are given,
+ * If no protection cert nor oldCert nor CSR nor subject is given,
* sender name is not known to the client and thus set to NULL-DN
*/
sender = ctx->cert != NULL ? X509_get_subject_name(ctx->cert) :
ctx->oldCert != NULL ? X509_get_subject_name(ctx->oldCert) :
+ ctx->p10CSR != NULL ? X509_REQ_get_subject_name(ctx->p10CSR) :
ctx->subjectName;
if (!ossl_cmp_hdr_set1_sender(hdr, sender))
return 0;
diff --git a/crypto/cmp/cmp_http.c b/crypto/cmp/cmp_http.c
index d29bfa8674ad..c0226e562a32 100644
--- a/crypto/cmp/cmp_http.c
+++ b/crypto/cmp/cmp_http.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -14,7 +14,6 @@
#include <openssl/asn1t.h>
#include <openssl/http.h>
-#include "internal/sockets.h"
#include <openssl/cmp.h>
#include "cmp_local.h"
@@ -25,12 +24,11 @@
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
-#include <openssl/cmp.h>
#include <openssl/err.h>
-static int keep_alive(int keep_alive, int body_type)
+static int keep_alive(int keep_alive, int body_type, BIO **bios)
{
- if (keep_alive != 0
+ if (keep_alive != 0 && bios == NULL
/*
* Ask for persistent connection only if may need more round trips.
* Do so even with disableConfirm because polling might be needed.
@@ -46,7 +44,6 @@ static int keep_alive(int keep_alive, int body_type)
/*
* Send the PKIMessage req and on success return the response, else NULL.
- * Any previous error queue entries will likely be removed by ERR_clear_error().
*/
OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req)
@@ -57,6 +54,7 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
int tls_used;
const ASN1_ITEM *it = ASN1_ITEM_rptr(OSSL_CMP_MSG);
BIO *req_mem, *rsp;
+ BIO **bios; /* optionally used as bio and rbio */
OSSL_CMP_MSG *res = NULL;
if (ctx == NULL || req == NULL) {
@@ -69,24 +67,40 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
if ((req_mem = ASN1_item_i2d_mem_bio(it, (const ASN1_VALUE *)req)) == NULL)
goto err;
+ bios = OSSL_CMP_CTX_get_transfer_cb_arg(ctx);
if (ctx->serverPort != 0)
BIO_snprintf(server_port, sizeof(server_port), "%d", ctx->serverPort);
- tls_used = OSSL_CMP_CTX_get_http_cb_arg(ctx) != NULL;
- if (ctx->http_ctx == NULL)
- ossl_cmp_log3(DEBUG, ctx, "connecting to CMP server %s:%s%s",
- ctx->server, server_port, tls_used ? " using TLS" : "");
+ tls_used = ctx->tls_used >= 0 ? ctx->tls_used != 0
+ : OSSL_CMP_CTX_get_http_cb_arg(ctx) != NULL; /* backward compat */
+ if (ctx->http_ctx == NULL) { /* using existing connection or yet not set up own connection */
+ const char *path = ctx->serverPath;
+
+ if (path == NULL)
+ path = "";
+ if (*path == '/')
+ path++;
+ if (bios == NULL)
+ ossl_cmp_log4(DEBUG, ctx,
+ "connecting to CMP server via http%s://%s:%s%s/%s",
+ tls_used ? "s" : "", ctx->server, server_port, path);
+ else
+ ossl_cmp_log3(DEBUG, ctx,
+ "using existing connection with CMP server %s%s and HTTP path /%s",
+ ctx->server, server_port, path);
+ }
rsp = OSSL_HTTP_transfer(&ctx->http_ctx, ctx->server, server_port,
ctx->serverPath, tls_used,
ctx->proxy, ctx->no_proxy,
- NULL /* bio */, NULL /* rbio */,
+ bios == NULL ? NULL : bios[0] /* bio */,
+ bios == NULL ? NULL : bios[1] /* rbio */,
ctx->http_cb, OSSL_CMP_CTX_get_http_cb_arg(ctx),
0 /* buf_size */, headers,
content_type_pkix, req_mem,
content_type_pkix, 1 /* expect_asn1 */,
OSSL_HTTP_DEFAULT_MAX_RESP_LEN,
ctx->msg_timeout,
- keep_alive(ctx->keep_alive, req->body->type));
+ keep_alive(ctx->keep_alive, req->body->type, bios));
BIO_free(req_mem);
res = (OSSL_CMP_MSG *)ASN1_item_d2i_bio(it, rsp, NULL);
BIO_free(rsp);
@@ -94,9 +108,11 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
if (ctx->http_ctx == NULL)
ossl_cmp_debug(ctx, "disconnected from CMP server");
/*
- * Note that on normal successful end of the transaction the connection
- * is not closed at this level, but this will be done by the CMP client
- * application via OSSL_CMP_CTX_free() or OSSL_CMP_CTX_reinit().
+ * Note that on normal successful end of the transaction the
+ * HTTP connection is not closed at this level if keep_alive(...) != 0.
+ * It should be closed by the CMP client application
+ * using OSSL_CMP_CTX_free() or OSSL_CMP_CTX_reinit().
+ * Any pre-existing bio (== ctx->transfer_cb_arg) is not freed.
*/
if (res != NULL)
ossl_cmp_debug(ctx, "finished reading response from CMP server");
diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h
index 8eeb56d4e0f0..bbca4e0ac565 100644
--- a/crypto/cmp/cmp_local.h
+++ b/crypto/cmp/cmp_local.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -25,7 +25,7 @@
# include <openssl/x509v3.h>
# include "crypto/x509.h"
-#define IS_NULL_DN(name) (X509_NAME_get_entry(name, 0) == NULL)
+# define IS_NULL_DN(name) (X509_NAME_get_entry(name, 0) == NULL)
/*
* this structure is used to store the context for CMP sessions
@@ -49,10 +49,13 @@ struct ossl_cmp_ctx_st {
int keep_alive; /* persistent connection: 0=no, 1=prefer, 2=require */
int msg_timeout; /* max seconds to wait for each CMP message round trip */
int total_timeout; /* max number of seconds an enrollment may take, incl. */
+ int tls_used; /* whether to use TLS for client-side HTTP connections */
/* attempts polling for a response if a 'waiting' PKIStatus is received */
time_t end_time; /* session start time + totaltimeout */
+# ifndef OPENSSL_NO_HTTP
OSSL_HTTP_bio_cb_t http_cb;
void *http_cb_arg; /* allows to store optional argument to cb */
+# endif
/* server authentication */
/*
@@ -61,6 +64,7 @@ struct ossl_cmp_ctx_st {
* certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf
*/
int unprotectedErrors;
+ int noCacheExtraCerts;
X509 *srvCert; /* certificate used to identify the server */
X509 *validatedSrvCert; /* caches any already validated server cert */
X509_NAME *expected_sender; /* expected sender in header of response */
@@ -78,7 +82,7 @@ struct ossl_cmp_ctx_st {
X509 *cert; /* protection cert used to identify and sign for MSG_SIG_ALG */
STACK_OF(X509) *chain; /* (cached) chain of protection cert including it */
EVP_PKEY *pkey; /* the key pair corresponding to cert */
- ASN1_OCTET_STRING *referenceValue; /* optional user name for MSG_MAC_ALG */
+ ASN1_OCTET_STRING *referenceValue; /* optional username for MSG_MAC_ALG */
ASN1_OCTET_STRING *secretValue; /* password/shared secret for MSG_MAC_ALG */
/* PBMParameters for MSG_MAC_ALG */
size_t pbm_slen; /* salt length, currently fixed to 16 */
@@ -92,6 +96,7 @@ struct ossl_cmp_ctx_st {
ASN1_OCTET_STRING *transactionID; /* the current transaction ID */
ASN1_OCTET_STRING *senderNonce; /* last nonce sent */
ASN1_OCTET_STRING *recipNonce; /* last nonce received */
+ ASN1_OCTET_STRING *first_senderNonce; /* sender nonce when starting to poll */
ASN1_UTF8STRING *freeText; /* optional string to include each msg */
STACK_OF(OSSL_CMP_ITAV) *geninfo_ITAVs;
int implicitConfirm; /* set implicitConfirm in IR/KUR/CR messages */
@@ -101,7 +106,8 @@ struct ossl_cmp_ctx_st {
/* certificate template */
EVP_PKEY *newPkey; /* explicit new private/public key for cert enrollment */
int newPkey_priv; /* flag indicating if newPkey contains private key */
- X509_NAME *issuer; /* issuer name to used in cert template */
+ X509_NAME *issuer; /* issuer name to used in cert template, also in rr */
+ ASN1_INTEGER *serialNumber; /* certificate serial number to use in rr */
int days; /* Number of days new certificates are asked to be valid for */
X509_NAME *subjectName; /* subject name to be used in cert template */
STACK_OF(GENERAL_NAME) *subjectAltNames; /* to add to the cert template */
@@ -118,7 +124,7 @@ struct ossl_cmp_ctx_st {
int revocationReason; /* revocation reason code to be included in RR */
STACK_OF(OSSL_CMP_ITAV) *genm_ITAVs; /* content of general message */
- /* result returned in responses */
+ /* result returned in responses, so far supporting only one certResponse */
int status; /* PKIStatus of last received IP/CP/KUP/RP/error or -1 */
OSSL_CMP_PKIFREETEXT *statusString; /* of last IP/CP/KUP/RP/error */
int failInfoCode; /* failInfoCode of last received IP/CP/KUP/error, or -1 */
@@ -202,6 +208,39 @@ typedef struct ossl_cmp_cakeyupdanncontent_st {
} OSSL_CMP_CAKEYUPDANNCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT)
+typedef struct ossl_cmp_rootcakeyupdate_st OSSL_CMP_ROOTCAKEYUPDATE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
+
+typedef struct ossl_cmp_certreqtemplate_st OSSL_CMP_CERTREQTEMPLATE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTREQTEMPLATE)
+
+/*-
+ * CRLSource ::= CHOICE {
+ * dpn [0] DistributionPointName,
+ * issuer [1] GeneralNames }
+ */
+
+typedef struct ossl_cmp_crlsource_st {
+ int type;
+ union {
+ DIST_POINT_NAME *dpn;
+ GENERAL_NAMES *issuer;
+ } value;
+} OSSL_CMP_CRLSOURCE;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLSOURCE)
+
+/*
+ * CRLStatus ::= SEQUENCE {
+ * source CRLSource,
+ * thisUpdate Time OPTIONAL }
+ */
+
+struct ossl_cmp_crlstatus_st {
+ OSSL_CMP_CRLSOURCE *source;
+ ASN1_TIME *thisUpdate;
+}; /* OSSL_CMP_CRLSTATUS */
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CRLSTATUS)
+
/*-
* declared already here as it will be used in OSSL_CMP_MSG (nested) and
* infoType and infoValue
@@ -247,6 +286,21 @@ struct ossl_cmp_itav_st {
OSSL_CMP_MSGS *origPKIMessage;
/* NID_id_it_suppLangTags - Supported Language Tags */
STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue;
+ /* NID_id_it_certProfile - Certificate Profile */
+ STACK_OF(ASN1_UTF8STRING) *certProfile;
+ /* NID_id_it_caCerts - CA Certificates */
+ STACK_OF(X509) *caCerts;
+ /* NID_id_it_rootCaCert - Root CA Certificate */
+ X509 *rootCaCert;
+ /* NID_id_it_rootCaKeyUpdate - Root CA Certificate Update */
+ OSSL_CMP_ROOTCAKEYUPDATE *rootCaKeyUpdate;
+ /* NID_id_it_certReqTemplate - Certificate Request Template */
+ OSSL_CMP_CERTREQTEMPLATE *certReqTemplate;
+ /* NID_id_it_crlStatusList - CRL Update Retrieval */
+ STACK_OF(OSSL_CMP_CRLSTATUS) *crlStatusList;
+ /* NID_id_it_crls - Certificate Status Lists */
+ STACK_OF(X509_CRL) *crls;
+
/* this is to be used for so far undeclared objects */
ASN1_TYPE *other;
} infoValue;
@@ -257,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)
@@ -272,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)
@@ -369,13 +423,15 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ERRORMSGCONTENT)
* -- as is used to create and verify the certificate signature
* certReqId INTEGER,
* -- to match this confirmation with the corresponding req/rep
- * statusInfo PKIStatusInfo OPTIONAL
+ * statusInfo PKIStatusInfo OPTIONAL,
+ * hashAlg [0] AlgorithmIdentifier OPTIONAL
* }
*/
struct ossl_cmp_certstatus_st {
ASN1_OCTET_STRING *certHash;
ASN1_INTEGER *certReqId;
OSSL_CMP_PKISI *statusInfo;
+ X509_ALGOR *hashAlg; /* 0 */
} /* OSSL_CMP_CERTSTATUS */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS)
typedef STACK_OF(OSSL_CMP_CERTSTATUS) OSSL_CMP_CERTCONFIRMCONTENT;
@@ -446,7 +502,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_POLLREPCONTENT)
/*-
* PKIHeader ::= SEQUENCE {
- * pvno INTEGER { cmp1999(1), cmp2000(2) },
+ * pvno INTEGER { cmp1999(1), cmp2000(2), cmp2021(3) },
* sender GeneralName,
* -- identifies the sender
* recipient GeneralName,
@@ -708,6 +764,7 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PROTECTEDPART)
* } -- or HMAC [RFC2104, RFC2202])
*/
/*-
+ * Not supported:
* id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
* DHBMParameter ::= SEQUENCE {
* owf AlgorithmIdentifier,
@@ -730,6 +787,32 @@ DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PROTECTEDPART)
* }
*/
+/*
+ * RootCaKeyUpdateContent ::= SEQUENCE {
+ * newWithNew CMPCertificate,
+ * newWithOld [0] CMPCertificate OPTIONAL,
+ * oldWithNew [1] CMPCertificate OPTIONAL
+ * }
+ */
+
+struct ossl_cmp_rootcakeyupdate_st {
+ X509 *newWithNew;
+ X509 *newWithOld;
+ X509 *oldWithNew;
+} /* OSSL_CMP_ROOTCAKEYUPDATE */;
+DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ROOTCAKEYUPDATE)
+
+/*-
+ * CertReqTemplateContent ::= SEQUENCE {
+ * certTemplate CertTemplate,
+ * keySpec Controls OPTIONAL
+ * }
+ */
+struct ossl_cmp_certreqtemplate_st {
+ OSSL_CRMF_CERTTEMPLATE *certTemplate;
+ OSSL_CMP_ATAVS *keySpec;
+} /* OSSL_CMP_CERTREQTEMPLATE */;
+
/* from cmp_asn.c */
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
@@ -777,7 +860,7 @@ int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
# define ossl_cmp_info(ctx, msg) ossl_cmp_log(INFO, ctx, msg)
# define ossl_cmp_debug(ctx, msg) ossl_cmp_log(DEBUG, ctx, msg)
# define ossl_cmp_trace(ctx, msg) ossl_cmp_log(TRACE, ctx, msg)
-int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert);
+int ossl_cmp_ctx_set1_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert);
int ossl_cmp_ctx_set_status(OSSL_CMP_CTX *ctx, int status);
int ossl_cmp_ctx_set0_statusString(OSSL_CMP_CTX *ctx,
OSSL_CMP_PKIFREETEXT *text);
@@ -790,6 +873,8 @@ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce);
EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx);
+int ossl_cmp_ctx_set1_first_senderNonce(OSSL_CMP_CTX *ctx,
+ const ASN1_OCTET_STRING *nonce);
/* from cmp_status.c */
int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si);
@@ -867,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);
@@ -906,8 +992,10 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm,
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);
@@ -925,6 +1013,8 @@ int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg, int accept_RAVerified);
/* from cmp_client.c */
+/* expected max time per msg round trip, used for last try during polling: */
+# define OSSL_CMP_EXPECTED_RESP_TIME 2
int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId,
int fail_info, const char *txt);
int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c
index c8e467f3c21f..055f14c8f861 100644
--- a/crypto/cmp/cmp_msg.c
+++ b/crypto/cmp/cmp_msg.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -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)
{
@@ -59,7 +62,6 @@ int ossl_cmp_msg_set0_libctx(OSSL_CMP_MSG *msg, OSSL_LIB_CTX *libctx,
return 1;
}
-
OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg)
{
if (msg == NULL) {
@@ -101,6 +103,34 @@ int OSSL_CMP_MSG_get_bodytype(const OSSL_CMP_MSG *msg)
return msg->body->type;
}
+X509_PUBKEY *OSSL_CMP_MSG_get0_certreq_publickey(const OSSL_CMP_MSG *msg)
+{
+ const OSSL_CRMF_MSGS *reqs;
+ const OSSL_CRMF_MSG *crm;
+ const OSSL_CRMF_CERTTEMPLATE *tmpl;
+ X509_PUBKEY *pubkey;
+
+ switch (OSSL_CMP_MSG_get_bodytype(msg)) {
+ case OSSL_CMP_PKIBODY_IR:
+ case OSSL_CMP_PKIBODY_CR:
+ case OSSL_CMP_PKIBODY_KUR:
+ reqs = msg->body->value.ir; /* value.ir is same for cr and kur */
+ if ((crm = sk_OSSL_CRMF_MSG_value(reqs, 0)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND);
+ return NULL;
+ }
+ if ((tmpl = OSSL_CRMF_MSG_get0_tmpl(crm)) == NULL
+ || (pubkey = OSSL_CRMF_CERTTEMPLATE_get0_publicKey(tmpl)) == NULL) {
+ ERR_raise(ERR_LIB_CMP, CRMF_R_POPO_MISSING_PUBLIC_KEY);
+ return NULL;
+ }
+ return pubkey;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return NULL;
+ }
+}
+
/* Add an extension to the referenced extension stack, which may be NULL */
static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
{
@@ -118,34 +148,6 @@ static int add1_extension(X509_EXTENSIONS **pexts, int nid, int crit, void *ex)
return res;
}
-/* Add extension list to the referenced extension stack, which may be NULL */
-static int add_extensions(STACK_OF(X509_EXTENSION) **target,
- const STACK_OF(X509_EXTENSION) *exts)
-{
- int i;
-
- if (target == NULL)
- return 0;
-
- for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
- X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
- ASN1_OBJECT *obj = X509_EXTENSION_get_object(ext);
- int idx = X509v3_get_ext_by_OBJ(*target, obj, -1);
-
- /* Does extension exist in target? */
- if (idx != -1) {
- /* Delete all extensions of same type */
- do {
- X509_EXTENSION_free(sk_X509_EXTENSION_delete(*target, idx));
- idx = X509v3_get_ext_by_OBJ(*target, obj, -1);
- } while (idx != -1);
- }
- if (!X509v3_add_ext(target, ext, -1))
- return 0;
- }
- return 1;
-}
-
/* Add a CRL revocation reason code to extension stack, which may be NULL */
static int add_crl_reason_extension(X509_EXTENSIONS **pexts, int reason_code)
{
@@ -272,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);
@@ -284,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;
@@ -298,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
@@ -307,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);
@@ -326,13 +336,13 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid)
&& (exts = X509_REQ_get_extensions(ctx->p10CSR)) == NULL)
goto err;
if (!ctx->SubjectAltName_nodefault && !HAS_SAN(ctx) && refcert != NULL
- && (default_sans = X509V3_get_d2i(X509_get0_extensions(refcert),
- NID_subject_alt_name, NULL, NULL))
- != NULL
+ && (default_sans = X509V3_get_d2i(X509_get0_extensions(refcert),
+ NID_subject_alt_name, NULL, NULL))
+ != NULL
&& !add1_extension(&exts, NID_subject_alt_name, crit, default_sans))
goto err;
- if (ctx->reqExtensions != NULL /* augment/override existing ones */
- && !add_extensions(&exts, ctx->reqExtensions))
+ if (sk_X509_EXTENSION_num(ctx->reqExtensions) > 0 /* augment/override existing ones */
+ && X509v3_add_extensions(&exts, ctx->reqExtensions) == NULL)
goto err;
if (sk_GENERAL_NAME_num(ctx->subjectAltNames) > 0
&& !add1_extension(&exts, NID_subject_alt_name,
@@ -442,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)
{
@@ -488,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))
@@ -519,27 +577,37 @@ OSSL_CMP_MSG *ossl_cmp_certrep_new(OSSL_CMP_CTX *ctx, int bodytype,
OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx)
{
OSSL_CMP_MSG *msg = NULL;
+ const X509_NAME *issuer = NULL;
+ const X509_NAME *subject = NULL;
+ const ASN1_INTEGER *serialNumber = NULL;
+ EVP_PKEY *pubkey = NULL;
OSSL_CMP_REVDETAILS *rd;
int ret;
- if (!ossl_assert(ctx != NULL && (ctx->oldCert != NULL
- || ctx->p10CSR != NULL)))
+ if (!ossl_assert(ctx != NULL
+ && (ctx->oldCert != NULL || ctx->p10CSR != NULL
+ || (ctx->serialNumber != NULL && ctx->issuer != NULL))))
return NULL;
if ((rd = OSSL_CMP_REVDETAILS_new()) == NULL)
goto err;
+ if (ctx->serialNumber != NULL && ctx->issuer != NULL) {
+ issuer = ctx->issuer;
+ serialNumber = ctx->serialNumber;
+ } else if (ctx->oldCert != NULL) {
+ issuer = X509_get_issuer_name(ctx->oldCert);
+ serialNumber = X509_get0_serialNumber(ctx->oldCert);
+ } else if (ctx->p10CSR != NULL) {
+ pubkey = X509_REQ_get0_pubkey(ctx->p10CSR);
+ subject = X509_REQ_get_subject_name(ctx->p10CSR);
+ } else {
+ goto err;
+ }
+
/* Fill the template from the contents of the certificate to be revoked */
- ret = ctx->oldCert != NULL
- ? OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
- NULL /* pubkey would be redundant */,
- NULL /* subject would be redundant */,
- X509_get_issuer_name(ctx->oldCert),
- X509_get0_serialNumber(ctx->oldCert))
- : OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails,
- X509_REQ_get0_pubkey(ctx->p10CSR),
- X509_REQ_get_subject_name(ctx->p10CSR),
- NULL, NULL);
+ ret = OSSL_CRMF_CERTTEMPLATE_fill(rd->certDetails, pubkey, subject,
+ issuer, serialNumber);
if (!ret)
goto err;
@@ -584,23 +652,20 @@ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
goto err;
rep = msg->body->value.rp;
- if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL)
+ if ((si1 = OSSL_CMP_PKISI_dup(si)) == NULL
+ || !sk_OSSL_CMP_PKISI_push(rep->status, si1))
goto err;
- if (!sk_OSSL_CMP_PKISI_push(rep->status, si1)) {
- OSSL_CMP_PKISI_free(si1);
- goto err;
- }
+ si1 = NULL; /* ownership transferred to rep->status */
if ((rep->revCerts = sk_OSSL_CRMF_CERTID_new_null()) == NULL)
goto err;
if (cid != NULL) {
- if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL)
+ if ((cid_copy = OSSL_CRMF_CERTID_dup(cid)) == NULL
+ || !sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy))
goto err;
- if (!sk_OSSL_CRMF_CERTID_push(rep->revCerts, cid_copy)) {
- OSSL_CRMF_CERTID_free(cid_copy);
- goto err;
- }
+
+ cid_copy = NULL; /* ownership transferred to rep->revCerts */
}
if (!unprotectedErrors
@@ -612,6 +677,8 @@ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, const OSSL_CMP_PKISI *si,
err:
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_RP);
+ OSSL_CMP_PKISI_free(si1);
+ OSSL_CRMF_CERTID_free(cid_copy);
OSSL_CMP_MSG_free(msg);
return NULL;
}
@@ -673,7 +740,7 @@ int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
}
/*
- * Creates a new General Message/Response with an empty itav stack
+ * Creates a new General Message/Response with a copy of the given itav stack
* returns a pointer to the PKIMessage on success, NULL on error
*/
static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,
@@ -787,6 +854,8 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int certReqId,
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_CERTSTATUS *certStatus = NULL;
+ EVP_MD *md;
+ int is_fallback;
ASN1_OCTET_STRING *certHash = NULL;
OSSL_CMP_PKISI *sinfo;
@@ -814,13 +883,23 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int certReqId,
/* set the ID of the certReq */
if (!ASN1_INTEGER_set(certStatus->certReqId, certReqId))
goto err;
+
+ certStatus->hashAlg = NULL;
/*
* The hash of the certificate, using the same hash algorithm
* as is used to create and verify the certificate signature.
- * If not available, a default hash algorithm is used.
+ * If not available, a fallback hash algorithm is used.
*/
- if ((certHash = X509_digest_sig(ctx->newCert, NULL, NULL)) == NULL)
+ if ((certHash = X509_digest_sig(ctx->newCert, &md, &is_fallback)) == NULL)
goto err;
+ if (is_fallback) {
+ if (!ossl_cmp_hdr_set_pvno(msg->header, OSSL_CMP_PVNO_3))
+ goto err;
+ if ((certStatus->hashAlg = X509_ALGOR_new()) == NULL)
+ goto err;
+ X509_ALGOR_set_md(certStatus->hashAlg, md);
+ }
+ EVP_MD_free(md);
if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash))
goto err;
@@ -962,8 +1041,7 @@ static int suitable_rid(const ASN1_INTEGER *certReqId, int rid)
return 1;
trid = ossl_cmp_asn1_get_int(certReqId);
-
- if (trid == OSSL_CMP_CERTREQID_NONE) {
+ if (trid <= OSSL_CMP_CERTREQID_INVALID) {
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
return 0;
}
@@ -1023,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);
@@ -1051,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);
@@ -1106,8 +1211,8 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_read(const char *file, OSSL_LIB_CTX *libctx,
}
msg = OSSL_CMP_MSG_new(libctx, propq);
- if (msg == NULL){
- ERR_raise(ERR_LIB_CMP, ERR_R_MALLOC_FAILURE);
+ if (msg == NULL) {
+ ERR_raise(ERR_LIB_CMP, ERR_R_CMP_LIB);
return NULL;
}
@@ -1178,3 +1283,13 @@ int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
{
return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);
}
+
+int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg)
+{
+ if (!ossl_assert(msg != NULL))
+ return 0;
+
+ return (OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_ERROR
+ && ossl_cmp_pkisi_get_status(msg->body->value.error->pKIStatusInfo)
+ == OSSL_CMP_PKISTATUS_waiting);
+}
diff --git a/crypto/cmp/cmp_protect.c b/crypto/cmp/cmp_protect.c
index 539f6534cd01..e4f3bffed720 100644
--- a/crypto/cmp/cmp_protect.c
+++ b/crypto/cmp/cmp_protect.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -10,6 +10,7 @@
*/
#include "cmp_local.h"
+#include "crypto/asn1.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/asn1t.h>
@@ -21,9 +22,11 @@
/*
* This function is also used by the internal verify_PBMAC() in cmp_vfy.c.
*
- * Calculate protection for given PKImessage according to
- * the algorithm and parameters in the message header's protectionAlg
+ * Calculate protection for |msg| according to |msg->header->protectionAlg|
* using the credentials, library context, and property criteria in the ctx.
+ * Unless |msg->header->protectionAlg| is PasswordBasedMAC,
+ * its value is completed according to |ctx->pkey| and |ctx->digest|,
+ * where the latter irrelevant in the case of Edwards curves.
*
* returns ASN1_BIT_STRING representing the protection on success, else NULL
*/
@@ -91,9 +94,8 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
if ((prot = ASN1_BIT_STRING_new()) == NULL)
goto end;
- /* OpenSSL defaults all bit strings to be encoded as ASN.1 NamedBitList */
- prot->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
- prot->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ /* OpenSSL by default encodes all bit strings as ASN.1 NamedBitList */
+ ossl_asn1_string_set_bits_left(prot, 0);
if (!ASN1_BIT_STRING_set(prot, protection, sig_len)) {
ASN1_BIT_STRING_free(prot);
prot = NULL;
@@ -104,23 +106,22 @@ ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_CTX *ctx,
OPENSSL_free(prot_part_der);
return prot;
} else {
- int md_nid;
- const EVP_MD *md = NULL;
+ const EVP_MD *md = ctx->digest;
+ char name[80] = "";
if (ctx->pkey == NULL) {
ERR_raise(ERR_LIB_CMP,
CMP_R_MISSING_KEY_INPUT_FOR_CREATING_PROTECTION);
return NULL;
}
- if (!OBJ_find_sigid_algs(OBJ_obj2nid(algorOID), &md_nid, NULL)
- || (md = EVP_get_digestbynid(md_nid)) == NULL) {
- ERR_raise(ERR_LIB_CMP, CMP_R_UNKNOWN_ALGORITHM_ID);
- return NULL;
- }
+ if (EVP_PKEY_get_default_digest_name(ctx->pkey, name, sizeof(name)) > 0
+ && strcmp(name, "UNDEF") == 0) /* at least for Ed25519, Ed448 */
+ md = NULL;
if ((prot = ASN1_BIT_STRING_new()) == NULL)
return NULL;
- if (ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART), NULL,
+ if (ASN1_item_sign_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART),
+ msg->header->protectionAlg, /* sets X509_ALGOR */
NULL, prot, &prot_part, NULL, ctx->pkey, md,
ctx->libctx, ctx->propq))
return prot;
@@ -129,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)
{
@@ -141,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;
@@ -185,15 +190,16 @@ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
* Create an X509_ALGOR structure for PasswordBasedMAC protection based on
* the pbm settings in the context
*/
-static int set_pbmac_algor(const OSSL_CMP_CTX *ctx, X509_ALGOR **alg)
+static X509_ALGOR *pbmac_algor(const OSSL_CMP_CTX *ctx)
{
OSSL_CRMF_PBMPARAMETER *pbm = NULL;
unsigned char *pbm_der = NULL;
int pbm_der_len;
ASN1_STRING *pbm_str = NULL;
+ X509_ALGOR *alg = NULL;
if (!ossl_assert(ctx != NULL))
- return 0;
+ return NULL;
pbm = OSSL_CRMF_pbmp_new(ctx->libctx, ctx->pbm_slen,
EVP_MD_get_type(ctx->pbm_owf), ctx->pbm_itercnt,
@@ -201,47 +207,18 @@ static int set_pbmac_algor(const OSSL_CMP_CTX *ctx, X509_ALGOR **alg)
pbm_str = ASN1_STRING_new();
if (pbm == NULL || pbm_str == NULL)
goto err;
-
if ((pbm_der_len = i2d_OSSL_CRMF_PBMPARAMETER(pbm, &pbm_der)) < 0)
goto err;
-
if (!ASN1_STRING_set(pbm_str, pbm_der, pbm_der_len))
goto err;
- if (*alg == NULL && (*alg = X509_ALGOR_new()) == NULL)
- goto err;
- OPENSSL_free(pbm_der);
-
- X509_ALGOR_set0(*alg, OBJ_nid2obj(NID_id_PasswordBasedMAC),
- V_ASN1_SEQUENCE, pbm_str);
- OSSL_CRMF_PBMPARAMETER_free(pbm);
- return 1;
-
+ alg = ossl_X509_ALGOR_from_nid(NID_id_PasswordBasedMAC,
+ V_ASN1_SEQUENCE, pbm_str);
err:
- ASN1_STRING_free(pbm_str);
+ if (alg == NULL)
+ ASN1_STRING_free(pbm_str);
OPENSSL_free(pbm_der);
OSSL_CRMF_PBMPARAMETER_free(pbm);
- return 0;
-}
-
-static int set_sig_algor(const OSSL_CMP_CTX *ctx, X509_ALGOR **alg)
-{
- int nid = 0;
- ASN1_OBJECT *algo = NULL;
-
- if (!OBJ_find_sigid_by_algs(&nid, EVP_MD_get_type(ctx->digest),
- EVP_PKEY_get_id(ctx->pkey))) {
- ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_KEY_TYPE);
- return 0;
- }
- if ((algo = OBJ_nid2obj(nid)) == NULL)
- return 0;
- if (*alg == NULL && (*alg = X509_ALGOR_new()) == NULL)
- return 0;
-
- if (X509_ALGOR_set0(*alg, algo, V_ASN1_UNDEF, NULL))
- return 1;
- ASN1_OBJECT_free(algo);
- return 0;
+ return alg;
}
static int set_senderKID(const OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg,
@@ -260,6 +237,7 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
/*
* For the case of re-protection remove pre-existing protection.
+ * Does not remove any pre-existing extraCerts.
*/
X509_ALGOR_free(msg->header->protectionAlg);
msg->header->protectionAlg = NULL;
@@ -271,7 +249,7 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
goto err;
} else if (ctx->secretValue != NULL) {
/* use PasswordBasedMac according to 5.1.3.1 if secretValue is given */
- if (!set_pbmac_algor(ctx, &msg->header->protectionAlg))
+ if ((msg->header->protectionAlg = pbmac_algor(ctx)) == NULL)
goto err;
if (!set_senderKID(ctx, msg, NULL))
goto err;
@@ -290,7 +268,7 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
goto err;
}
- if (!set_sig_algor(ctx, &msg->header->protectionAlg))
+ if ((msg->header->protectionAlg = X509_ALGOR_new()) == NULL)
goto err;
/* set senderKID to keyIdentifier of the cert according to 5.1.1 */
if (!set_senderKID(ctx, msg, X509_get0_subject_key_id(ctx->cert)))
@@ -306,6 +284,7 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
goto err;
}
if (!ctx->unprotectedSend
+ /* protect according to msg->header->protectionAlg partly set above */
&& ((msg->protection = ossl_cmp_calc_protection(ctx, msg)) == NULL))
goto err;
diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c
index 96f977636ca2..6a833f83c538 100644
--- a/crypto/cmp/cmp_server.c
+++ b/crypto/cmp/cmp_server.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2025 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -20,11 +20,11 @@
#include <openssl/err.h>
/* the context for the generic CMP server */
-struct ossl_cmp_srv_ctx_st
-{
- void *custom_ctx; /* pointer to application-specific server context */
- OSSL_CMP_CTX *ctx; /* Client CMP context, reusing transactionID etc. */
- int certReqId; /* id of last ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */
+struct ossl_cmp_srv_ctx_st {
+ OSSL_CMP_CTX *ctx; /* CMP client context reused for transactionID etc. */
+ void *custom_ctx; /* application-specific server context */
+ int certReqId; /* of ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */
+ int polling; /* current transaction is in polling mode */
OSSL_CMP_SRV_cert_request_cb_t process_cert_request;
OSSL_CMP_SRV_rr_cb_t process_rr;
@@ -32,6 +32,8 @@ struct ossl_cmp_srv_ctx_st
OSSL_CMP_SRV_error_cb_t process_error;
OSSL_CMP_SRV_certConf_cb_t process_certConf;
OSSL_CMP_SRV_pollReq_cb_t process_pollReq;
+ OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery;
+ OSSL_CMP_SRV_clean_transaction_cb_t clean_transaction;
int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */
int acceptUnprotected; /* Accept requests with no/invalid prot. */
@@ -59,6 +61,7 @@ OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq)
if ((ctx->ctx = OSSL_CMP_CTX_new(libctx, propq)) == NULL)
goto err;
ctx->certReqId = OSSL_CMP_CERTREQID_INVALID;
+ ctx->polling = 0;
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
@@ -89,6 +92,19 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
return 1;
}
+int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx,
+ OSSL_CMP_SRV_delayed_delivery_cb_t delay,
+ OSSL_CMP_SRV_clean_transaction_cb_t clean)
+{
+ if (srv_ctx == NULL) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
+ return 0;
+ }
+ srv_ctx->delayed_delivery = delay;
+ srv_ctx->clean_transaction = clean;
+ return 1;
+}
+
OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL) {
@@ -149,6 +165,46 @@ int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
return 1;
}
+/* return error msg with waiting status if polling is initiated, else NULL */
+static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ int ret;
+ unsigned long err;
+ int status = OSSL_CMP_PKISTATUS_waiting,
+ fail_info = 0, errorCode = 0;
+ const char *txt = NULL, *details = NULL;
+ OSSL_CMP_PKISI *si;
+ OSSL_CMP_MSG *msg;
+
+ if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL
+ && srv_ctx->delayed_delivery != NULL))
+ return NULL;
+
+ ret = srv_ctx->delayed_delivery(srv_ctx, req);
+ if (ret == 0)
+ return NULL;
+ if (ret == 1) {
+ srv_ctx->polling = 1;
+ } else {
+ status = OSSL_CMP_PKISTATUS_rejection;
+ fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_systemFailure;
+ txt = "server application error";
+ err = ERR_peek_error();
+ errorCode = ERR_GET_REASON(err);
+ details = ERR_reason_error_string(err);
+ }
+
+ si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt);
+ if (si == NULL)
+ return NULL;
+
+ msg = ossl_cmp_error_new(srv_ctx->ctx, si, errorCode, details,
+ srv_ctx->sendUnprotectedErrors);
+ OSSL_CMP_PKISI_free(si);
+ return msg;
+}
+
/*
* Processes an ir/cr/p10cr/kur and returns a certification response.
* Only handles the first certification request contained in req
@@ -160,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;
@@ -195,20 +252,23 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
-
- if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) {
+ if ((crm = sk_OSSL_CRMF_MSG_value(reqs, 0)) == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND);
return NULL;
}
certReqId = OSSL_CRMF_MSG_get_certReqId(crm);
- if (certReqId != OSSL_CMP_CERTREQID) {
+ if (certReqId != OSSL_CMP_CERTREQID) { /* so far, only possible value */
ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
- return 0;
+ 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,
@@ -222,6 +282,8 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
&certOut, &chainOut, &caPubs);
if (si == NULL)
goto err;
+ if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting)
+ srv_ctx->polling = 1;
/* set OSSL_CMP_OPT_IMPLICIT_CONFIRM if and only if transaction ends */
if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx,
OSSL_CMP_OPT_IMPLICIT_CONFIRM,
@@ -230,19 +292,24 @@ 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)
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_CREATING_CERTREP);
err:
OSSL_CMP_PKISI_free(si);
X509_free(certOut);
- sk_X509_pop_free(chainOut, X509_free);
- sk_X509_pop_free(caPubs, X509_free);
+ OSSL_CMP_CTX_set0_newPkey(srv_ctx->ctx, 0, NULL);
+ OSSL_STACK_OF_X509_free(chainOut);
+ OSSL_STACK_OF_X509_free(caPubs);
return msg;
}
@@ -264,9 +331,8 @@ static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
-
- if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr,
- OSSL_CMP_REVREQSID)) == NULL) {
+ details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr, 0);
+ if (details == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
@@ -355,7 +421,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
} else {
if (num > 1)
ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored");
- status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID);
+ status = sk_OSSL_CMP_CERTSTATUS_value(ccc, 0);
}
if (status != NULL) {
@@ -386,38 +452,96 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
return msg;
}
+/* pollReq is handled separately, to avoid recursive call */
+static OSSL_CMP_MSG *process_non_polling_request(OSSL_CMP_SRV_CTX *srv_ctx,
+ const OSSL_CMP_MSG *req)
+{
+ OSSL_CMP_MSG *rsp = NULL;
+
+ if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL
+ && req->body != NULL))
+ return NULL;
+
+ switch (OSSL_CMP_MSG_get_bodytype(req)) {
+ case OSSL_CMP_PKIBODY_IR:
+ case OSSL_CMP_PKIBODY_CR:
+ case OSSL_CMP_PKIBODY_P10CR:
+ case OSSL_CMP_PKIBODY_KUR:
+ if (srv_ctx->process_cert_request == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+ else
+ rsp = process_cert_request(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_RR:
+ if (srv_ctx->process_rr == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+ else
+ rsp = process_rr(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_GENM:
+ if (srv_ctx->process_genm == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+ else
+ rsp = process_genm(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_ERROR:
+ if (srv_ctx->process_error == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+ else
+ rsp = process_error(srv_ctx, req);
+ break;
+ case OSSL_CMP_PKIBODY_CERTCONF:
+ if (srv_ctx->process_certConf == NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+ else
+ rsp = process_certConf(srv_ctx, req);
+ break;
+
+ case OSSL_CMP_PKIBODY_POLLREQ:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ break;
+ default:
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
+ break;
+ }
+
+ return rsp;
+}
+
static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_POLLREQCONTENT *prc;
OSSL_CMP_POLLREQ *pr;
int certReqId;
- OSSL_CMP_MSG *certReq;
+ OSSL_CMP_MSG *orig_req;
int64_t check_after = 0;
OSSL_CMP_MSG *msg = NULL;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
+ if (!srv_ctx->polling) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ return NULL;
+ }
+
prc = req->body->value.pollReq;
if (sk_OSSL_CMP_POLLREQ_num(prc) != 1) {
ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
- pr = sk_OSSL_CMP_POLLREQ_value(prc, OSSL_CMP_CERTREQID);
+ pr = sk_OSSL_CMP_POLLREQ_value(prc, 0);
certReqId = ossl_cmp_asn1_get_int(pr->certReqId);
- if (certReqId != srv_ctx->certReqId) {
- ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID);
- return NULL;
- }
if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId,
- &certReq, &check_after))
+ &orig_req, &check_after))
return NULL;
- if (certReq != NULL) {
- msg = process_cert_request(srv_ctx, certReq);
- OSSL_CMP_MSG_free(certReq);
+ if (orig_req != NULL) {
+ srv_ctx->polling = 0;
+ msg = process_non_polling_request(srv_ctx, orig_req);
+ OSSL_CMP_MSG_free(orig_req);
} else {
if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId,
check_after)) == NULL)
@@ -487,6 +611,12 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName))
goto err;
+ if (srv_ctx->polling && req_type != OSSL_CMP_PKIBODY_POLLREQ
+ && req_type != OSSL_CMP_PKIBODY_ERROR) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_EXPECTED_POLLREQ);
+ goto err;
+ }
+
switch (req_type) {
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
@@ -496,10 +626,8 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
case OSSL_CMP_PKIBODY_GENM:
case OSSL_CMP_PKIBODY_ERROR:
if (ctx->transactionID != NULL) {
- char *tid;
+ char *tid = i2s_ASN1_OCTET_STRING(NULL, ctx->transactionID);
- tid = OPENSSL_buf2hexstr(ctx->transactionID->data,
- ctx->transactionID->length);
if (tid != NULL)
ossl_cmp_log1(WARN, ctx,
"Assuming that last transaction with ID=%s got aborted",
@@ -510,6 +638,13 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
if (!OSSL_CMP_CTX_set1_transactionID(ctx, NULL)
|| !OSSL_CMP_CTX_set1_senderNonce(ctx, NULL))
goto err;
+
+ if (srv_ctx->clean_transaction != NULL
+ && !srv_ctx->clean_transaction(srv_ctx, NULL)) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE);
+ goto err;
+ }
+
break;
default:
/* transactionID should be already initialized */
@@ -529,49 +664,17 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
if (!req_verified)
goto err;
- switch (req_type) {
- case OSSL_CMP_PKIBODY_IR:
- case OSSL_CMP_PKIBODY_CR:
- case OSSL_CMP_PKIBODY_P10CR:
- case OSSL_CMP_PKIBODY_KUR:
- if (srv_ctx->process_cert_request == NULL)
- ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
- else
- rsp = process_cert_request(srv_ctx, req);
- break;
- case OSSL_CMP_PKIBODY_RR:
- if (srv_ctx->process_rr == NULL)
- ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
- else
- rsp = process_rr(srv_ctx, req);
- break;
- case OSSL_CMP_PKIBODY_GENM:
- if (srv_ctx->process_genm == NULL)
- ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
- else
- rsp = process_genm(srv_ctx, req);
- break;
- case OSSL_CMP_PKIBODY_ERROR:
- if (srv_ctx->process_error == NULL)
- ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
- else
- rsp = process_error(srv_ctx, req);
- break;
- case OSSL_CMP_PKIBODY_CERTCONF:
- if (srv_ctx->process_certConf == NULL)
- ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
- else
- rsp = process_certConf(srv_ctx, req);
- break;
- case OSSL_CMP_PKIBODY_POLLREQ:
+ if (req_type == OSSL_CMP_PKIBODY_POLLREQ) {
if (srv_ctx->process_pollReq == NULL)
- ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
+ ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY);
else
rsp = process_pollReq(srv_ctx, req);
- break;
- default:
- ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY);
- break;
+ } else {
+ if (srv_ctx->delayed_delivery != NULL
+ && (rsp = delayed_delivery(srv_ctx, req)) != NULL) {
+ goto err;
+ }
+ rsp = process_non_polling_request(srv_ctx, req);
}
err:
@@ -581,6 +684,7 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
int flags = 0;
unsigned long err = ERR_peek_error_data(&data, &flags);
int fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_badRequest;
+ /* fail_info is not very specific */
OSSL_CMP_PKISI *si = NULL;
if (!req_verified) {
@@ -626,10 +730,19 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
break;
/* fall through */
+ case OSSL_CMP_PKIBODY_ERROR:
+ if (rsp != NULL && ossl_cmp_is_error_with_waiting(rsp))
+ break;
+ /* fall through */
+
case OSSL_CMP_PKIBODY_RP:
case OSSL_CMP_PKIBODY_PKICONF:
case OSSL_CMP_PKIBODY_GENP:
- case OSSL_CMP_PKIBODY_ERROR:
+ /* Other terminating response message types are not supported */
+ srv_ctx->certReqId = OSSL_CMP_CERTREQID_INVALID;
+ /* Prepare for next transaction, ignoring any errors here: */
+ if (srv_ctx->clean_transaction != NULL)
+ (void)srv_ctx->clean_transaction(srv_ctx, ctx->transactionID);
(void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL);
(void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL);
ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */
diff --git a/crypto/cmp/cmp_status.c b/crypto/cmp/cmp_status.c
index 68144aa4fed8..b9086d84f846 100644
--- a/crypto/cmp/cmp_status.c
+++ b/crypto/cmp/cmp_status.c
@@ -184,11 +184,11 @@ char *snprint_PKIStatusInfo_parts(int status, int fail_info,
|| (status_string = ossl_cmp_PKIStatus_to_string(status)) == NULL)
return NULL;
-#define ADVANCE_BUFFER \
- if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
- return NULL; \
- write_ptr += printed_chars; \
- bufsize -= printed_chars;
+#define ADVANCE_BUFFER \
+ if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
+ return NULL; \
+ write_ptr += printed_chars; \
+ bufsize -= printed_chars;
printed_chars = BIO_snprintf(write_ptr, bufsize, "%s", status_string);
ADVANCE_BUFFER;
diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c
index 7cf27cc9d4b4..f3c21c5d914c 100644
--- a/crypto/cmp/cmp_util.c
+++ b/crypto/cmp/cmp_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
@@ -53,8 +53,7 @@ static OSSL_CMP_severity parse_level(const char *level)
if (end_level == NULL)
return -1;
- if (strncmp(level, OSSL_CMP_LOG_PREFIX,
- strlen(OSSL_CMP_LOG_PREFIX)) == 0)
+ if (HAS_PREFIX(level, OSSL_CMP_LOG_PREFIX))
level += strlen(OSSL_CMP_LOG_PREFIX);
len = end_level - level;
if (len > max_level_len)
@@ -190,7 +189,7 @@ void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn)
BIO_free(bio);
}
#else
- /* ERR_raise(ERR_LIB_CMP, CMP_R_NO_STDIO) makes no sense during error printing */
+ /* ERR_raise(..., CMP_R_NO_STDIO) would make no sense here */
#endif
} else {
if (log_fn(component, file, line, OSSL_CMP_LOG_ERR, msg) <= 0)
@@ -244,6 +243,7 @@ int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
const ASN1_OCTET_STRING *src)
{
ASN1_OCTET_STRING *new;
+
if (tgt == NULL) {
ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
return 0;
diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c
index b9951045c2e8..47bf38b2af5d 100644
--- a/crypto/cmp/cmp_vfy.c
+++ b/crypto/cmp/cmp_vfy.c
@@ -34,7 +34,8 @@ static int verify_signature(const OSSL_CMP_CTX *cmp_ctx,
return 0;
bio = BIO_new(BIO_s_mem()); /* may be NULL */
-
+ if (bio == NULL)
+ return 0;
/* verify that keyUsage, if present, contains digitalSignature */
if (!cmp_ctx->ignore_keyusage
&& (X509_get_key_usage(cert) & X509v3_KU_DIGITAL_SIGNATURE) == 0) {
@@ -138,6 +139,24 @@ int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
return valid;
}
+static int verify_cb_cert(X509_STORE *ts, X509 *cert, int err)
+{
+ X509_STORE_CTX_verify_cb verify_cb;
+ X509_STORE_CTX *csc;
+ int ok = 0;
+
+ if (ts == NULL || (verify_cb = X509_STORE_get_verify_cb(ts)) == NULL)
+ return ok;
+ if ((csc = X509_STORE_CTX_new()) != NULL
+ && X509_STORE_CTX_init(csc, ts, cert, NULL)) {
+ X509_STORE_CTX_set_error(csc, err);
+ X509_STORE_CTX_set_current_cert(csc, cert);
+ ok = (*verify_cb)(0, csc);
+ }
+ X509_STORE_CTX_free(csc);
+ return ok;
+}
+
/* Return 0 if expect_name != NULL and there is no matching actual_name */
static int check_name(const OSSL_CMP_CTX *ctx, int log_success,
const char *actual_desc, const X509_NAME *actual_name,
@@ -156,8 +175,8 @@ static int check_name(const OSSL_CMP_CTX *ctx, int log_success,
str = X509_NAME_oneline(actual_name, NULL, 0);
if (X509_NAME_cmp(actual_name, expect_name) == 0) {
if (log_success && str != NULL)
- ossl_cmp_log2(INFO, ctx, " subject matches %s: %s", expect_desc,
- str);
+ ossl_cmp_log3(INFO, ctx, " %s matches %s: %s",
+ actual_desc, expect_desc, str);
OPENSSL_free(str);
return 1;
}
@@ -186,7 +205,7 @@ static int check_kid(const OSSL_CMP_CTX *ctx,
ossl_cmp_warn(ctx, "missing Subject Key Identifier in certificate");
return 0;
}
- str = OPENSSL_buf2hexstr(ckid->data, ckid->length);
+ str = i2s_ASN1_OCTET_STRING(NULL, ckid);
if (ASN1_OCTET_STRING_cmp(ckid, skid) == 0) {
if (str != NULL)
ossl_cmp_log1(INFO, ctx, " subjectKID matches senderKID: %s", str);
@@ -197,7 +216,7 @@ static int check_kid(const OSSL_CMP_CTX *ctx,
if (str != NULL)
ossl_cmp_log1(INFO, ctx, " cert Subject Key Identifier = %s", str);
OPENSSL_free(str);
- if ((str = OPENSSL_buf2hexstr(skid->data, skid->length)) != NULL)
+ if ((str = i2s_ASN1_OCTET_STRING(NULL, skid)) != NULL)
ossl_cmp_log1(INFO, ctx, " does not match senderKID = %s", str);
OPENSSL_free(str);
return 0;
@@ -255,9 +274,14 @@ static int cert_acceptable(const OSSL_CMP_CTX *ctx,
time_cmp = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert),
X509_get0_notAfter(cert));
if (time_cmp != 0) {
+ int err = time_cmp > 0 ? X509_V_ERR_CERT_HAS_EXPIRED
+ : X509_V_ERR_CERT_NOT_YET_VALID;
+
ossl_cmp_warn(ctx, time_cmp > 0 ? "cert has expired"
: "cert is not yet valid");
- return 0;
+ if (ctx->log_cb != NULL /* logging not temporarily disabled */
+ && verify_cb_cert(ts, cert, err) <= 0)
+ return 0;
}
if (!check_name(ctx, 1,
@@ -353,7 +377,7 @@ static int check_msg_given_cert(const OSSL_CMP_CTX *ctx, X509 *cert,
/*-
* Try all certs in given list for verifying msg, normally or in 3GPP mode.
* If already_checked1 == NULL then certs are assumed to be the msg->extraCerts.
- * On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
+ * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
*/
static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs,
const char *desc,
@@ -382,13 +406,7 @@ static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs,
if (mode_3gpp ? check_cert_path_3gpp(ctx, msg, cert)
: check_cert_path(ctx, ctx->trusted, cert)) {
/* store successful sender cert for further msgs in transaction */
- if (!X509_up_ref(cert))
- return 0;
- if (!ossl_cmp_ctx_set0_validatedSrvCert(ctx, cert)) {
- X509_free(cert);
- return 0;
- }
- return 1;
+ return ossl_cmp_ctx_set1_validatedSrvCert(ctx, cert);
}
}
if (in_extraCerts && n_acceptable_certs == 0)
@@ -399,21 +417,21 @@ static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs,
/*-
* Verify msg trying first ctx->untrusted, which should include extraCerts
* at its front, then trying the trusted certs in truststore (if any) of ctx.
- * On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
+ * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
*/
static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
int mode_3gpp)
{
int ret = 0;
- if (mode_3gpp
- && ((!ctx->permitTAInExtraCertsForIR
- || OSSL_CMP_MSG_get_bodytype(msg) != OSSL_CMP_PKIBODY_IP)))
+ if (ctx->permitTAInExtraCertsForIR
+ && OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_IP)
+ ossl_cmp_info(ctx, mode_3gpp ?
+ "normal mode failed; trying now 3GPP mode trusting extraCerts"
+ : "trying first normal mode using trust store");
+ else if (mode_3gpp)
return 0;
- ossl_cmp_info(ctx,
- mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts"
- : "trying first normal mode using trust store");
if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts",
NULL, NULL, msg, mode_3gpp))
return 1;
@@ -426,25 +444,20 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
: "no trusted store");
} else {
STACK_OF(X509) *trusted = X509_STORE_get1_all_certs(ctx->trusted);
+
ret = check_msg_with_certs(ctx, trusted,
mode_3gpp ? "self-issued extraCerts"
: "certs in trusted store",
msg->extraCerts, ctx->untrusted,
msg, mode_3gpp);
- sk_X509_pop_free(trusted, X509_free);
+ OSSL_STACK_OF_X509_free(trusted);
}
return ret;
}
-static int no_log_cb(const char *func, const char *file, int line,
- OSSL_CMP_severity level, const char *msg)
-{
- return 1;
-}
-
/*-
* Verify message signature with any acceptable and valid candidate cert.
- * On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
+ * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
*/
static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
{
@@ -459,6 +472,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
if (sender == NULL || msg->body == NULL)
return 0; /* other NULL cases already have been checked */
if (sender->type != GEN_DIRNAME) {
+ /* So far, only X509_NAME is supported */
ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
return 0;
}
@@ -468,7 +482,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
/* enable clearing irrelevant errors in attempts to validate sender certs */
(void)ERR_set_mark();
- ctx->log_cb = no_log_cb; /* temporarily disable logging */
+ ctx->log_cb = NULL; /* temporarily disable logging */
/*
* try first cached scrt, used successfully earlier in same transaction,
@@ -481,7 +495,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
return 1;
}
/* cached sender cert has shown to be no more successfully usable */
- (void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL);
+ (void)ossl_cmp_ctx_set1_validatedSrvCert(ctx, NULL);
/* re-do the above check (just) for adding diagnostic information */
ossl_cmp_info(ctx,
"trying to verify msg signature with previously validated cert");
@@ -500,8 +514,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
(void)ERR_clear_last_mark();
sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0);
- skid_str = skid == NULL ? NULL
- : OPENSSL_buf2hexstr(skid->data, skid->length);
+ skid_str = skid == NULL ? NULL : i2s_ASN1_OCTET_STRING(NULL, skid);
if (ctx->log_cb != NULL) {
ossl_cmp_info(ctx, "trying to verify msg signature with a valid cert that..");
if (sname != NULL)
@@ -537,7 +550,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
* the sender certificate can have been pinned by providing it in ctx->srvCert,
* else it is searched in msg->extraCerts, ctx->untrusted, in ctx->trusted
* (in this order) and is path is validated against ctx->trusted.
- * On success cache the found cert using ossl_cmp_ctx_set0_validatedSrvCert().
+ * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
*
* If ctx->permitTAInExtraCertsForIR is true and when validating a CMP IP msg,
* the trust anchor for validating the IP msg may be taken from msg->extraCerts
@@ -599,7 +612,7 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
break;
}
ossl_cmp_debug(ctx,
- "sucessfully validated PBM-based CMP message protection");
+ "successfully validated PBM-based CMP message protection");
return 1;
}
ossl_cmp_warn(ctx, "verifying PBM-based CMP message protection failed");
@@ -624,15 +637,17 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_TRUST_ANCHOR);
return 0;
}
- if (check_msg_find_cert(ctx, msg))
+ if (check_msg_find_cert(ctx, msg)) {
+ ossl_cmp_debug(ctx,
+ "successfully validated signature-based CMP message protection using trust store");
return 1;
+ }
} else { /* use pinned sender cert */
/* use ctx->srvCert for signature check even if not acceptable */
if (verify_signature(ctx, msg, scrt)) {
ossl_cmp_debug(ctx,
- "sucessfully validated signature-based CMP message protection");
-
- return 1;
+ "successfully validated signature-based CMP message protection using pinned server cert");
+ return ossl_cmp_ctx_set1_validatedSrvCert(ctx, scrt);
}
ossl_cmp_warn(ctx, "CMP message signature verification failed");
ERR_raise(ERR_LIB_CMP, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG);
@@ -642,12 +657,35 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
return 0;
}
+static int check_transactionID_or_nonce(ASN1_OCTET_STRING *expected,
+ ASN1_OCTET_STRING *actual, int reason)
+{
+ if (expected != NULL
+ && (actual == NULL || ASN1_OCTET_STRING_cmp(expected, actual) != 0)) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ char *expected_str, *actual_str;
+
+ expected_str = i2s_ASN1_OCTET_STRING(NULL, expected);
+ actual_str = actual == NULL ? NULL: i2s_ASN1_OCTET_STRING(NULL, actual);
+ ERR_raise_data(ERR_LIB_CMP, reason,
+ "expected = %s, actual = %s",
+ expected_str == NULL ? "?" : expected_str,
+ actual == NULL ? "(none)" :
+ actual_str == NULL ? "?" : actual_str);
+ OPENSSL_free(expected_str);
+ OPENSSL_free(actual_str);
+ return 0;
+#endif
+ }
+ return 1;
+}
+
/*-
* Check received message (i.e., response by server or request from client)
* Any msg->extraCerts are prepended to ctx->untrusted.
*
* Ensures that:
- * its sender is of appropriate type (curently only X509_NAME) and
+ * its sender is of appropriate type (currently only X509_NAME) and
* matches any expected sender or srvCert subject given in the ctx
* it has a valid body type
* its protection is valid (or invalid/absent, but only if a callback function
@@ -667,68 +705,94 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
{
OSSL_CMP_PKIHEADER *hdr;
const X509_NAME *expected_sender;
+ int num_untrusted, num_added, res;
if (!ossl_assert(ctx != NULL && msg != NULL && msg->header != NULL))
return 0;
hdr = OSSL_CMP_MSG_get0_header(msg);
- /* validate sender name of received msg */
- if (hdr->sender->type != GEN_DIRNAME) {
- ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
- return 0;
- }
- /*
- * Compare actual sender name of response with expected sender name.
- * Mitigates risk to accept misused PBM secret
- * or misused certificate of an unauthorized entity of a trusted hierarchy.
- */
+ /* If expected_sender is given, validate sender name of received msg */
expected_sender = ctx->expected_sender;
if (expected_sender == NULL && ctx->srvCert != NULL)
expected_sender = X509_get_subject_name(ctx->srvCert);
- if (!check_name(ctx, 0, "sender DN field", hdr->sender->d.directoryName,
- "expected sender", expected_sender))
- return 0;
+ if (expected_sender != NULL) {
+ const X509_NAME *actual_sender;
+ char *str;
+
+ if (hdr->sender->type != GEN_DIRNAME) {
+ ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
+ return 0;
+ }
+ actual_sender = hdr->sender->d.directoryName;
+ /*
+ * Compare actual sender name of response with expected sender name.
+ * Mitigates risk of accepting misused PBM secret or
+ * misused certificate of an unauthorized entity of a trusted hierarchy.
+ */
+ if (!check_name(ctx, 0, "sender DN field", actual_sender,
+ "expected sender", expected_sender)) {
+ str = X509_NAME_oneline(actual_sender, NULL, 0);
+ ERR_raise_data(ERR_LIB_CMP, CMP_R_UNEXPECTED_SENDER,
+ str != NULL ? str : "<unknown>");
+ OPENSSL_free(str);
+ return 0;
+ }
+ }
/* Note: if recipient was NULL-DN it could be learned here if needed */
- if (sk_X509_num(msg->extraCerts) > 10)
- ossl_cmp_warn(ctx,
- "received CMP message contains more than 10 extraCerts");
+ num_added = sk_X509_num(msg->extraCerts);
+ if (num_added > 10)
+ ossl_cmp_log1(WARN, ctx, "received CMP message contains %d extraCerts",
+ num_added);
/*
* Store any provided extraCerts in ctx for use in OSSL_CMP_validate_msg()
* and for future use, such that they are available to ctx->certConf_cb and
* the peer does not need to send them again in the same transaction.
* Note that it does not help validating the message before storing the
* extraCerts because they do not belong to the protected msg part anyway.
- * For efficiency, the extraCerts are prepended so they get used first.
+ * The extraCerts are prepended. Allows simple removal if they shall not be
+ * cached. Also they get used first, which is likely good for efficiency.
*/
- if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
- /* this allows self-signed certs */
- X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
- | X509_ADD_FLAG_PREPEND))
+ num_untrusted = ctx->untrusted == NULL ? 0 : sk_X509_num(ctx->untrusted);
+ res = ossl_x509_add_certs_new(&ctx->untrusted, msg->extraCerts,
+ /* this allows self-signed certs */
+ X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
+ | X509_ADD_FLAG_PREPEND);
+ num_added = (ctx->untrusted == NULL ? 0 : sk_X509_num(ctx->untrusted))
+ - num_untrusted;
+ if (!res) {
+ while (num_added-- > 0)
+ X509_free(sk_X509_shift(ctx->untrusted));
return 0;
+ }
- /* validate message protection */
- if (hdr->protectionAlg != NULL) {
- /* detect explicitly permitted exceptions for invalid protection */
- if (!OSSL_CMP_validate_msg(ctx, msg)
- && (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) {
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
- return 0;
+ if (hdr->protectionAlg != NULL)
+ res = OSSL_CMP_validate_msg(ctx, msg)
+ /* explicitly permitted exceptions for invalid protection: */
+ || (cb != NULL && (*cb)(ctx, msg, 1, cb_arg) > 0);
+ else
+ /* explicitly permitted exceptions for missing protection: */
+ res = cb != NULL && (*cb)(ctx, msg, 0, cb_arg) > 0;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ res = 1; /* support more aggressive fuzzing by letting invalid msg pass */
#endif
- }
- } else {
- /* detect explicitly permitted exceptions for missing protection */
- if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) {
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+
+ /* remove extraCerts again if not caching */
+ if (ctx->noCacheExtraCerts)
+ while (num_added-- > 0)
+ X509_free(sk_X509_shift(ctx->untrusted));
+
+ if (!res) {
+ if (hdr->protectionAlg != NULL)
+ ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
+ else
ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
- return 0;
-#endif
- }
+ return 0;
}
/* check CMP version number in header */
- if (ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO) {
+ if (ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO_2
+ && ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO_3) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PVNO);
return 0;
@@ -743,26 +807,30 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
}
/* compare received transactionID with the expected one in previous msg */
- if (ctx->transactionID != NULL
- && (hdr->transactionID == NULL
- || ASN1_OCTET_STRING_cmp(ctx->transactionID,
- hdr->transactionID) != 0)) {
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- ERR_raise(ERR_LIB_CMP, CMP_R_TRANSACTIONID_UNMATCHED);
+ if (!check_transactionID_or_nonce(ctx->transactionID, hdr->transactionID,
+ CMP_R_TRANSACTIONID_UNMATCHED))
return 0;
-#endif
- }
+ /*
+ * enable clearing irrelevant errors
+ * in attempts to validate recipient nonce in case of delayed delivery.
+ */
+ (void)ERR_set_mark();
/* compare received nonce with the one we sent */
- if (ctx->senderNonce != NULL
- && (msg->header->recipNonce == NULL
- || ASN1_OCTET_STRING_cmp(ctx->senderNonce,
- hdr->recipNonce) != 0)) {
-#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
- ERR_raise(ERR_LIB_CMP, CMP_R_RECIPNONCE_UNMATCHED);
- return 0;
-#endif
+ if (!check_transactionID_or_nonce(ctx->senderNonce, hdr->recipNonce,
+ CMP_R_RECIPNONCE_UNMATCHED)) {
+ /* check if we are polling and received final response */
+ if (ctx->first_senderNonce == NULL
+ || OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_POLLREP
+ /* compare received nonce with our sender nonce at poll start */
+ || !check_transactionID_or_nonce(ctx->first_senderNonce,
+ hdr->recipNonce,
+ CMP_R_RECIPNONCE_UNMATCHED)) {
+ (void)ERR_clear_last_mark();
+ return 0;
+ }
}
+ (void)ERR_pop_to_mark();
/* if not yet present, learn transactionID */
if (ctx->transactionID == NULL
@@ -777,18 +845,6 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
if (!ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce))
return 0;
- /*
- * Store any provided extraCerts in ctx for future use,
- * such that they are available to ctx->certConf_cb and
- * the peer does not need to send them again in the same transaction.
- * For efficiency, the extraCerts are prepended so they get used first.
- */
- if (!X509_add_certs(ctx->untrusted, msg->extraCerts,
- /* this allows self-signed certs */
- X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
- | X509_ADD_FLAG_PREPEND))
- return 0;
-
if (ossl_cmp_hdr_get_protection_nid(hdr) == NID_id_PasswordBasedMAC) {
/*
* RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is