mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-17 20:19:29 +00:00
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.
189 lines
7.2 KiB
C
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;
|
|
}
|