Files
Open_Ultra_SAST/benchmarks/pairs/vfc/openssl-cve-2026-63073/fixed.c
T
Marius Ciepluch 0116f9bea6 feat(real-world-vfc-slice): add labeled OpenSSL/Firefox/Chromium/curl pair corpus
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows)
into benchmarks/pairs/vfc with provenance and a JSONL training manifest.
Score the slice as an honesty dashboard (ousast pairs --slice vfc);
keep the pair gate on the local fixtures only.
2026-09-04 16:45:38 +02:00

189 lines
7.2 KiB
C

/* Provenance: openssl/openssl ossl_cmp_msg_check_update (fixed).
* repo: openssl/openssl
* commit: a7e5a6eea8fd3ccca6b6fbba031a5fbf8a3d93b4
* parent: 1e8c398db67404babd3e5af999bb6bd86f720c76
* commit_url: https://github.com/openssl/openssl/commit/a7e5a6eea8fd3ccca6b6fbba031a5fbf8a3d93b4
* cve: CVE-2026-63073
* license: Apache-2.0
* function: ossl_cmp_msg_check_update
* relpath: crypto/cmp/cmp_vfy.c
*/
int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
ossl_cmp_allow_unprotected_cb_t cb, int cb_arg)
{
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);
/* 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 (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,
"%s", str != NULL ? str : "<unknown>");
OPENSSL_free(str);
return 0;
}
}
/* Note: if recipient was NULL-DN it could be learned here if needed */
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.
* The extraCerts are prepended. Allows simple removal if they shall not be
* cached. Also they get used first, which is likely good for efficiency.
*/
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;
}
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
/*
* remove extraCerts again if not caching
* or if we failed validation above, lest a remote user
* starts sending us lots of certificates in invalid messages
* leading to a DOS from unbounded certificate stack growth
*/
if (ctx->noCacheExtraCerts || res != 1)
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;
}
/* check CMP version number in header */
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;
#endif
}
if (OSSL_CMP_MSG_get_bodytype(msg) < 0) {
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
ERR_raise(ERR_LIB_CMP, CMP_R_PKIBODY_ERROR);
return 0;
#endif
}
/* compare received transactionID with the expected one in previous msg */
if (!check_transactionID_or_nonce(ctx->transactionID, hdr->transactionID,
CMP_R_TRANSACTIONID_UNMATCHED))
return 0;
/*
* 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 (!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
&& !OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID))
return 0;
/*
* RFC 4210 section 5.1.1 states: the recipNonce is copied from
* the senderNonce of the previous message in the transaction.
* --> Store for setting in next message
*/
if (!ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce))
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
* "shared secret information", then any certificate transported in
* the caPubs field may be directly trusted as a root CA
* certificate by the initiator.'
*/
switch (OSSL_CMP_MSG_get_bodytype(msg)) {
case OSSL_CMP_PKIBODY_IP:
case OSSL_CMP_PKIBODY_CP:
case OSSL_CMP_PKIBODY_KUP:
case OSSL_CMP_PKIBODY_CCP:
if (ctx->trusted != NULL) {
STACK_OF(X509) *certs = msg->body->value.ip->caPubs;
/* value.ip is same for cp, kup, and ccp */
if (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, certs, 0))
/* adds both self-issued and not self-issued certs */
return 0;
}
break;
default:
break;
}
}
return 1;
}