Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/crypto/cmp/cmp_vfy.c
Line
Count
Source
1
/*
2
 * Copyright 2007-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 * Copyright Nokia 2007-2020
4
 * Copyright Siemens AG 2015-2020
5
 *
6
 * Licensed under the Apache License 2.0 (the "License").  You may not use
7
 * this file except in compliance with the License.  You can obtain a copy
8
 * in the file LICENSE in the source distribution or at
9
 * https://www.openssl.org/source/license.html
10
 */
11
12
/* CMP functions for PKIMessage checking */
13
14
#include "cmp_local.h"
15
16
/* Verify a message protected by signature according to RFC section 5.1.3.3 */
17
static int verify_signature(const OSSL_CMP_CTX *cmp_ctx,
18
    const OSSL_CMP_MSG *msg, X509 *cert)
19
3.66k
{
20
3.66k
    OSSL_CMP_PROTECTEDPART prot_part;
21
3.66k
    EVP_PKEY *pubkey = NULL;
22
3.66k
    BIO *bio;
23
3.66k
    int res = 0;
24
25
3.66k
    if (!ossl_assert(cmp_ctx != NULL && msg != NULL && cert != NULL))
26
0
        return 0;
27
28
3.66k
    bio = BIO_new(BIO_s_mem()); /* may be NULL */
29
3.66k
    if (bio == NULL)
30
0
        return 0;
31
    /* verify that keyUsage, if present, contains digitalSignature */
32
3.66k
    if (!cmp_ctx->ignore_keyusage
33
3.66k
        && (X509_get_key_usage(cert) & X509v3_KU_DIGITAL_SIGNATURE) == 0) {
34
381
        ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_KEY_USAGE_DIGITALSIGNATURE);
35
381
        goto sig_err;
36
381
    }
37
38
3.28k
    pubkey = X509_get_pubkey(cert);
39
3.28k
    if (pubkey == NULL) {
40
1.57k
        ERR_raise(ERR_LIB_CMP, CMP_R_FAILED_EXTRACTING_PUBKEY);
41
1.57k
        goto sig_err;
42
1.57k
    }
43
44
1.70k
    prot_part.header = msg->header;
45
1.70k
    prot_part.body = msg->body;
46
47
1.70k
    if (ASN1_item_verify_ex(ASN1_ITEM_rptr(OSSL_CMP_PROTECTEDPART),
48
1.70k
            msg->header->protectionAlg, msg->protection,
49
1.70k
            &prot_part, NULL, pubkey, cmp_ctx->libctx,
50
1.70k
            cmp_ctx->propq)
51
1.70k
        > 0) {
52
55
        res = 1;
53
55
        goto end;
54
55
    }
55
56
3.60k
sig_err:
57
3.60k
    res = ossl_x509_print_ex_brief(bio, cert, X509_FLAG_NO_EXTENSIONS);
58
3.60k
    ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_SIGNATURE);
59
3.60k
    if (res) {
60
3.60k
        ERR_add_error_txt(NULL, "\n");
61
3.60k
        ERR_add_error_mem_bio(NULL, bio);
62
3.60k
    }
63
3.60k
    res = 0;
64
65
3.66k
end:
66
3.66k
    EVP_PKEY_free(pubkey);
67
3.66k
    BIO_free(bio);
68
69
3.66k
    return res;
70
3.60k
}
71
72
/* Verify a message protected with PBMAC */
73
static int verify_PBMAC(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
74
1.27k
{
75
1.27k
    ASN1_BIT_STRING *protection = NULL;
76
1.27k
    int valid = 0;
77
78
    /* generate expected protection for the message */
79
1.27k
    if ((protection = ossl_cmp_calc_protection(ctx, msg)) == NULL)
80
883
        return 0; /* failed to generate protection string! */
81
82
394
    valid = msg->protection != NULL && msg->protection->length >= 0
83
394
        && msg->protection->type == protection->type
84
394
        && msg->protection->length == protection->length
85
307
        && CRYPTO_memcmp(msg->protection->data, protection->data,
86
307
               protection->length)
87
307
            == 0;
88
394
    ASN1_BIT_STRING_free(protection);
89
394
    if (!valid)
90
394
        ERR_raise(ERR_LIB_CMP, CMP_R_WRONG_PBM_VALUE);
91
92
394
    return valid;
93
1.27k
}
94
95
/*-
96
 * Attempt to validate certificate and path using any given store with trusted
97
 * certs (possibly including CRLs and a cert verification callback function)
98
 * and non-trusted intermediate certs from the given ctx.
99
 *
100
 * Returns 1 on successful validation and 0 otherwise.
101
 */
102
int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx,
103
    X509_STORE *trusted_store, X509 *cert)
104
55
{
105
55
    int valid = 0;
106
55
    X509_STORE_CTX *csc = NULL;
107
55
    int err;
108
109
55
    if (ctx == NULL || cert == NULL) {
110
0
        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
111
0
        return 0;
112
0
    }
113
114
55
    if (trusted_store == NULL) {
115
55
        ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_TRUST_STORE);
116
55
        return 0;
117
55
    }
118
119
0
    if ((csc = X509_STORE_CTX_new_ex(ctx->libctx, ctx->propq)) == NULL
120
0
        || !X509_STORE_CTX_init(csc, trusted_store,
121
0
            cert, ctx->untrusted))
122
0
        goto err;
123
124
0
    valid = X509_verify_cert(csc) > 0;
125
126
    /* make sure suitable error is queued even if callback did not do */
127
0
    err = ERR_peek_last_error();
128
0
    if (!valid && ERR_GET_REASON(err) != CMP_R_POTENTIALLY_INVALID_CERTIFICATE)
129
0
        ERR_raise(ERR_LIB_CMP, CMP_R_POTENTIALLY_INVALID_CERTIFICATE);
130
131
0
err:
132
    /* directly output any fresh errors, needed for check_msg_find_cert() */
133
0
    OSSL_CMP_CTX_print_errors(ctx);
134
0
    X509_STORE_CTX_free(csc);
135
0
    return valid;
136
0
}
137
138
static int verify_cb_cert(X509_STORE *ts, X509 *cert, int err)
139
4.66k
{
140
4.66k
    X509_STORE_CTX_verify_cb verify_cb;
141
4.66k
    X509_STORE_CTX *csc;
142
4.66k
    int ok = 0;
143
144
4.66k
    if (ts == NULL || (verify_cb = X509_STORE_get_verify_cb(ts)) == NULL)
145
4.66k
        return ok;
146
0
    if ((csc = X509_STORE_CTX_new()) != NULL
147
0
        && X509_STORE_CTX_init(csc, ts, cert, NULL)) {
148
0
        X509_STORE_CTX_set_error(csc, err);
149
0
        X509_STORE_CTX_set_current_cert(csc, cert);
150
0
        ok = (*verify_cb)(0, csc);
151
0
    }
152
0
    X509_STORE_CTX_free(csc);
153
0
    return ok;
154
4.66k
}
155
156
/* Return 0 if expect_name != NULL and there is no matching actual_name */
157
static int check_name(const OSSL_CMP_CTX *ctx, int log_success,
158
    const char *actual_desc, const X509_NAME *actual_name,
159
    const char *expect_desc, const X509_NAME *expect_name)
160
9.57k
{
161
9.57k
    char *str;
162
163
9.57k
    if (expect_name == NULL)
164
0
        return 1; /* no expectation, thus trivially fulfilled */
165
166
    /* make sure that a matching name is there */
167
9.57k
    if (actual_name == NULL) {
168
0
        ossl_cmp_log1(WARN, ctx, "missing %s", actual_desc);
169
0
        return 0;
170
0
    }
171
9.57k
    str = X509_NAME_oneline(actual_name, NULL, 0);
172
9.57k
    if (X509_NAME_cmp(actual_name, expect_name) == 0) {
173
4.21k
        if (log_success && str != NULL)
174
4.21k
            ossl_cmp_log3(INFO, ctx, " %s matches %s: %s",
175
4.21k
                actual_desc, expect_desc, str);
176
4.21k
        OPENSSL_free(str);
177
4.21k
        return 1;
178
4.21k
    }
179
180
5.36k
    if (str != NULL)
181
5.36k
        ossl_cmp_log2(INFO, ctx, " actual name in %s = %s", actual_desc, str);
182
5.36k
    OPENSSL_free(str);
183
5.36k
    if ((str = X509_NAME_oneline(expect_name, NULL, 0)) != NULL)
184
5.36k
        ossl_cmp_log2(INFO, ctx, " does not match %s = %s", expect_desc, str);
185
5.36k
    OPENSSL_free(str);
186
5.36k
    return 0;
187
9.57k
}
188
189
/* Return 0 if skid != NULL and there is no matching subject key ID in cert */
190
static int check_kid(const OSSL_CMP_CTX *ctx,
191
    const ASN1_OCTET_STRING *ckid,
192
    const ASN1_OCTET_STRING *skid)
193
4.21k
{
194
4.21k
    char *str;
195
196
4.21k
    if (skid == NULL)
197
1.63k
        return 1; /* no expectation, thus trivially fulfilled */
198
199
    /* make sure that the expected subject key identifier is there */
200
2.57k
    if (ckid == NULL) {
201
183
        ossl_cmp_warn(ctx, "missing Subject Key Identifier in certificate");
202
183
        return 0;
203
183
    }
204
2.39k
    str = i2s_ASN1_OCTET_STRING(NULL, ckid);
205
2.39k
    if (ASN1_OCTET_STRING_cmp(ckid, skid) == 0) {
206
2.22k
        if (str != NULL)
207
2.22k
            ossl_cmp_log1(INFO, ctx, " subjectKID matches senderKID: %s", str);
208
2.22k
        OPENSSL_free(str);
209
2.22k
        return 1;
210
2.22k
    }
211
212
166
    if (str != NULL)
213
166
        ossl_cmp_log1(INFO, ctx, " cert Subject Key Identifier = %s", str);
214
166
    OPENSSL_free(str);
215
166
    if ((str = i2s_ASN1_OCTET_STRING(NULL, skid)) != NULL)
216
166
        ossl_cmp_log1(INFO, ctx, " does not match senderKID    = %s", str);
217
166
    OPENSSL_free(str);
218
166
    return 0;
219
2.39k
}
220
221
static int already_checked(const X509 *cert,
222
    const STACK_OF(X509) *already_checked)
223
42.7k
{
224
42.7k
    int i;
225
226
64.7k
    for (i = sk_X509_num(already_checked /* may be NULL */); i > 0; i--)
227
36.2k
        if (X509_cmp(sk_X509_value(already_checked, i - 1), cert) == 0)
228
14.2k
            return 1;
229
28.4k
    return 0;
230
42.7k
}
231
232
/*-
233
 * Check if the given cert is acceptable as sender cert of the given message.
234
 * The subject DN must match, the subject key ID as well if present in the msg,
235
 * and the cert must be current (checked if ctx->trusted is not NULL).
236
 * Note that cert revocation etc. is checked by OSSL_CMP_validate_cert_path().
237
 *
238
 * Returns 0 on error or not acceptable, else 1.
239
 */
240
static int cert_acceptable(const OSSL_CMP_CTX *ctx,
241
    const char *desc1, const char *desc2, X509 *cert,
242
    const STACK_OF(X509) *already_checked1,
243
    const STACK_OF(X509) *already_checked2,
244
    const OSSL_CMP_MSG *msg)
245
10.9k
{
246
10.9k
    X509_STORE *ts = ctx->trusted;
247
10.9k
    int self_issued = X509_check_issued(cert, cert) == X509_V_OK;
248
10.9k
    char *str;
249
10.9k
    X509_VERIFY_PARAM *vpm = ts != NULL ? X509_STORE_get0_param(ts) : NULL;
250
10.9k
    int err;
251
252
10.9k
    ossl_cmp_log3(INFO, ctx, " considering %s%s %s with..",
253
10.9k
        self_issued ? "self-issued " : "", desc1, desc2);
254
10.9k
    if ((str = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL)
255
10.9k
        ossl_cmp_log1(INFO, ctx, "  subject = %s", str);
256
10.9k
    OPENSSL_free(str);
257
10.9k
    if (!self_issued) {
258
9.23k
        str = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
259
9.23k
        if (str != NULL)
260
9.23k
            ossl_cmp_log1(INFO, ctx, "  issuer  = %s", str);
261
9.23k
        OPENSSL_free(str);
262
9.23k
    }
263
264
10.9k
    if (already_checked(cert, already_checked1)
265
5.46k
        || already_checked(cert, already_checked2)) {
266
5.46k
        ossl_cmp_info(ctx, " cert has already been checked");
267
5.46k
        return 0;
268
5.46k
    }
269
270
5.46k
    if (!X509_check_certificate_times(vpm, cert, &err)) {
271
4.68k
        const char *message;
272
273
4.68k
        switch (err) {
274
66
        case X509_V_ERR_CERT_NOT_YET_VALID:
275
66
            message = "cert is not yet valid";
276
66
            break;
277
1.91k
        case X509_V_ERR_CERT_HAS_EXPIRED:
278
1.91k
            message = "cert has expired";
279
1.91k
            break;
280
1.49k
        case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
281
1.49k
            message = "cert has an invalid not before field";
282
1.49k
            break;
283
1.20k
        case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
284
1.20k
            message = "cert has an invalid not after field";
285
1.20k
            break;
286
0
        default:
287
0
            message = "cert is invalid for an unspecfied reason";
288
0
            break;
289
4.68k
        }
290
291
4.68k
        ossl_cmp_warn(ctx, message);
292
4.68k
        if (ctx->log_cb != NULL /* logging not temporarily disabled */
293
2.34k
            && verify_cb_cert(ts, cert, err) <= 0)
294
2.34k
            return 0;
295
4.68k
    }
296
297
3.11k
    if (!check_name(ctx, 1,
298
3.11k
            "cert subject", X509_get_subject_name(cert),
299
3.11k
            "sender field", msg->header->sender->d.directoryName))
300
1.77k
        return 0;
301
302
1.33k
    if (!check_kid(ctx, X509_get0_subject_key_id(cert), msg->header->senderKID))
303
140
        return 0;
304
    /* prevent misleading error later in case x509v3_cache_extensions() fails */
305
1.19k
    if (!ossl_x509v3_cache_extensions(cert)) {
306
47
        ossl_cmp_warn(ctx, "cert appears to be invalid");
307
47
        return 0;
308
47
    }
309
1.15k
    if (!verify_signature(ctx, msg, cert)) {
310
1.13k
        ossl_cmp_warn(ctx, "msg signature verification failed");
311
1.13k
        return 0;
312
1.13k
    }
313
    /* acceptable also if there is no senderKID in msg header */
314
21
    ossl_cmp_info(ctx, " cert seems acceptable");
315
21
    return 1;
316
1.15k
}
317
318
static int check_cert_path(const OSSL_CMP_CTX *ctx, X509_STORE *store,
319
    X509 *scrt)
320
55
{
321
55
    if (OSSL_CMP_validate_cert_path(ctx, store, scrt))
322
0
        return 1;
323
324
55
    ossl_cmp_warn(ctx,
325
55
        "msg signature validates but cert path validation failed");
326
55
    return 0;
327
55
}
328
329
/*
330
 * Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security
331
 * (NDS); Authentication Framework (AF)], only to use for IP messages
332
 * and if the ctx option is explicitly set: use self-issued certificates from
333
 * extraCerts as trust anchors when validating the CMP message protection cert
334
 * in this and any subsequent responses from the server in the same transaction,
335
 * but only if these extraCerts can also be used as trust anchors for validating
336
 * the newly enrolled certificate received in the IP message.
337
 */
338
static int check_cert_path_3gpp(const OSSL_CMP_CTX *ctx,
339
    const OSSL_CMP_MSG *msg, X509 *scrt)
340
0
{
341
0
    int valid = 0;
342
0
    X509_STORE *store;
343
0
    STACK_OF(X509) *extraCerts;
344
345
0
    if (!ctx->permitTAInExtraCertsForIR)
346
0
        return 0;
347
348
    /*
349
     * Initially, use extraCerts from the IP message.
350
     * For subsequent msgs (pollRep or PKIConf) in the same transaction,
351
     * use extraCertsIn remembered from earlier message (typically, the IP message).
352
     * The extraCertsIn field will be cleared by OSSL_CMP_CTX_reinit().
353
     */
354
0
    extraCerts = ctx->extraCertsIn == NULL ? msg->extraCerts : ctx->extraCertsIn;
355
0
    if ((store = X509_STORE_new()) == NULL
356
0
        || !ossl_cmp_X509_STORE_add1_certs(store, extraCerts,
357
0
            1 /* self-issued only */))
358
0
        goto err;
359
360
    /* store does not include CRLs */
361
0
    valid = OSSL_CMP_validate_cert_path(ctx, store, scrt);
362
0
    if (!valid) {
363
0
        ossl_cmp_warn(ctx,
364
0
            "also exceptional 3GPP mode cert path validation failed");
365
0
    } else if (OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_IP) {
366
        /*
367
         * verify that the newly enrolled certificate (which assumed rid ==
368
         * OSSL_CMP_CERTREQID) can also be validated with the same trusted store
369
         */
370
0
        OSSL_CMP_CERTRESPONSE *crep = ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip,
371
0
            OSSL_CMP_CERTREQID);
372
0
        X509 *newcrt = NULL;
373
374
0
        valid = crep != NULL
375
0
            && (newcrt = ossl_cmp_certresponse_get1_cert(ctx, crep)) != NULL
376
0
            && OSSL_CMP_validate_cert_path(ctx, store, newcrt);
377
0
        X509_free(newcrt);
378
0
    }
379
380
0
err:
381
0
    X509_STORE_free(store);
382
0
    return valid;
383
0
}
384
385
/* checks protection of msg but not cert revocation nor cert chain */
386
static int check_msg_given_cert(const OSSL_CMP_CTX *ctx, X509 *cert,
387
    const OSSL_CMP_MSG *msg)
388
0
{
389
0
    return cert_acceptable(ctx, "previously validated", "sender cert",
390
0
        cert, NULL, NULL, msg);
391
0
}
392
393
/*-
394
 * Try all certs in given list for verifying msg, normally or in 3GPP mode.
395
 * If already_checked1 == NULL then certs are assumed to be the msg->extraCerts.
396
 * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
397
 */
398
static int check_msg_with_certs(OSSL_CMP_CTX *ctx, const STACK_OF(X509) *certs,
399
    const char *desc,
400
    const STACK_OF(X509) *already_checked1,
401
    const STACK_OF(X509) *already_checked2,
402
    const OSSL_CMP_MSG *msg, int mode_3gpp)
403
14.6k
{
404
14.6k
    int in_extraCerts = already_checked1 == NULL;
405
14.6k
    int n_acceptable_certs = 0;
406
14.6k
    int i;
407
408
14.6k
    if (sk_X509_num(certs) <= 0) {
409
1.96k
        ossl_cmp_log1(INFO, ctx, "no %s", desc);
410
1.96k
        return 0;
411
1.96k
    }
412
413
41.1k
    for (i = 0; i < sk_X509_num(certs); i++) { /* certs may be NULL */
414
28.4k
        X509 *cert = sk_X509_value(certs, i);
415
416
28.4k
        if (!ossl_assert(cert != NULL))
417
0
            return 0;
418
28.4k
        if (!cert_acceptable(ctx, "cert from", desc, cert,
419
28.4k
                already_checked1, already_checked2, msg))
420
28.4k
            continue;
421
55
        n_acceptable_certs++;
422
55
        if (mode_3gpp ? check_cert_path_3gpp(ctx, msg, cert)
423
55
                      : check_cert_path(ctx, ctx->trusted, cert)) {
424
            /* store successful sender cert for further msgs in transaction */
425
0
            return ossl_cmp_ctx_set1_validatedSrvCert(ctx, cert);
426
0
        }
427
55
    }
428
12.7k
    if (in_extraCerts && n_acceptable_certs == 0)
429
6.29k
        ossl_cmp_log1(WARN, ctx, "no acceptable %s", desc);
430
12.7k
    return 0;
431
12.7k
}
432
433
/*-
434
 * Verify msg trying first ctx->untrusted, which should include extraCerts
435
 * at its front, then trying the trusted certs in truststore (if any) of ctx.
436
 * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
437
 */
438
static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
439
    int mode_3gpp)
440
14.6k
{
441
14.6k
    int ret = 0;
442
443
14.6k
    if (ctx->permitTAInExtraCertsForIR
444
0
        && OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_IP)
445
14.6k
        ossl_cmp_info(ctx, mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts" : "trying first normal mode using trust store");
446
14.6k
    else if (mode_3gpp)
447
7.33k
        return 0;
448
449
7.33k
    if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts",
450
7.33k
            NULL, NULL, msg, mode_3gpp))
451
0
        return 1;
452
7.33k
    if (check_msg_with_certs(ctx, ctx->untrusted, "untrusted certs",
453
7.33k
            msg->extraCerts, NULL, msg, mode_3gpp))
454
0
        return 1;
455
456
7.33k
    if (ctx->trusted == NULL) {
457
7.33k
        ossl_cmp_warn(ctx, mode_3gpp ? "no self-issued extraCerts" : "no trusted store");
458
7.33k
    } else {
459
0
        STACK_OF(X509) *trusted = X509_STORE_get1_all_certs(ctx->trusted);
460
461
0
        ret = check_msg_with_certs(ctx, trusted,
462
0
            mode_3gpp ? "self-issued extraCerts"
463
0
                      : "certs in trusted store",
464
0
            msg->extraCerts, ctx->untrusted,
465
0
            msg, mode_3gpp);
466
0
        OSSL_STACK_OF_X509_free(trusted);
467
0
    }
468
7.33k
    return ret;
469
7.33k
}
470
471
/*-
472
 * Verify message signature with any acceptable and valid candidate cert.
473
 * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
474
 */
475
static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
476
3.66k
{
477
3.66k
    X509 *scrt = ctx->validatedSrvCert; /* previous successful sender cert */
478
3.66k
    GENERAL_NAME *sender = msg->header->sender;
479
3.66k
    char *sname = NULL;
480
3.66k
    char *skid_str = NULL;
481
3.66k
    const ASN1_OCTET_STRING *skid = msg->header->senderKID;
482
3.66k
    OSSL_CMP_log_cb_t backup_log_cb = ctx->log_cb;
483
3.66k
    int res = 0;
484
485
3.66k
    if (sender == NULL || msg->body == NULL)
486
0
        return 0; /* other NULL cases already have been checked */
487
3.66k
    if (sender->type != GEN_DIRNAME) {
488
        /* So far, only X509_NAME is supported */
489
0
        ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
490
0
        return 0;
491
0
    }
492
493
    /* dump any hitherto errors to avoid confusion when printing further ones */
494
3.66k
    OSSL_CMP_CTX_print_errors(ctx);
495
496
    /* enable clearing irrelevant errors in attempts to validate sender certs */
497
3.66k
    (void)ERR_set_mark();
498
3.66k
    ctx->log_cb = NULL; /* temporarily disable logging */
499
500
3.66k
    if (scrt != NULL) {
501
        /*-
502
         * try first using cached message sender cert (in 'scrt' variable),
503
         * which was used successfully earlier in the same transaction
504
         * (assuming that the certificate itself was not revoked meanwhile and
505
         *  is a good guess for use in validating also the current message)
506
         */
507
0
        if (check_msg_given_cert(ctx, scrt, msg)) {
508
0
            ctx->log_cb = backup_log_cb;
509
0
            (void)ERR_pop_to_mark();
510
0
            return 1;
511
0
        }
512
        /* cached sender cert has shown to be no more successfully usable */
513
        /* re-do the above check (just) for adding diagnostic information */
514
0
        ossl_cmp_info(ctx,
515
0
            "trying to verify msg signature with previously validated cert");
516
0
        ctx->log_cb = backup_log_cb;
517
0
        (void)check_msg_given_cert(ctx, scrt, msg);
518
0
        ctx->log_cb = NULL;
519
0
        (void)ossl_cmp_ctx_set1_validatedSrvCert(ctx, NULL); /* this invalidates scrt */
520
0
    }
521
522
3.66k
    res = check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */)
523
3.66k
        || check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
524
525
3.66k
    ctx->log_cb = backup_log_cb; /* re-enable logging */
526
    /* discard any previous diagnostic information on trying to use certs */
527
3.66k
    (void)ERR_pop_to_mark();
528
529
3.66k
    if (res)
530
0
        goto end;
531
    /* failed finding a sender cert that verifies the message signature */
532
533
3.66k
    sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0);
534
3.66k
    skid_str = skid == NULL ? NULL : i2s_ASN1_OCTET_STRING(NULL, skid);
535
3.66k
    if (ctx->log_cb != NULL) {
536
3.66k
        ossl_cmp_info(ctx, "trying to verify msg signature with a valid cert that..");
537
3.66k
        if (sname != NULL)
538
3.66k
            ossl_cmp_log1(INFO, ctx, "matches msg sender    = %s", sname);
539
3.66k
        if (skid_str != NULL)
540
2.14k
            ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str);
541
1.52k
        else
542
3.66k
            ossl_cmp_info(ctx, "while msg header does not contain senderKID");
543
        /* re-do the above checks (just) for adding diagnostic information */
544
3.66k
        (void)check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */);
545
3.66k
        (void)check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
546
3.66k
    }
547
548
3.66k
    ERR_raise(ERR_LIB_CMP, CMP_R_NO_SUITABLE_SENDER_CERT);
549
3.66k
    if (sname != NULL) {
550
3.66k
        ERR_add_error_txt(NULL, "for msg sender name = ");
551
3.66k
        ERR_add_error_txt(NULL, sname);
552
3.66k
    }
553
3.66k
    if (skid_str != NULL) {
554
2.14k
        ERR_add_error_txt(" and ", "for msg senderKID = ");
555
2.14k
        ERR_add_error_txt(NULL, skid_str);
556
2.14k
    }
557
558
3.66k
end:
559
3.66k
    OPENSSL_free(sname);
560
3.66k
    OPENSSL_free(skid_str);
561
3.66k
    return res;
562
3.66k
}
563
564
/*-
565
 * Validate the protection of the given PKIMessage using either password-
566
 * based mac (PBM) or a signature algorithm. In the case of signature algorithm,
567
 * the sender certificate can have been pinned by providing it in ctx->srvCert,
568
 * else it is searched in msg->extraCerts, ctx->untrusted, in ctx->trusted
569
 * (in this order) and is path is validated against ctx->trusted.
570
 * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert().
571
 *
572
 * If ctx->permitTAInExtraCertsForIR is true, when validating a CMP IP message,
573
 * trust anchors for validating the IP message (and any subsequent responses
574
 * by the server in the same transaction) may be taken from msg->extraCerts
575
 * if self-issued certificates are found there that can also be used
576
 * to validate the newly enrolled certificate returned in the IP msg.
577
 * This is according to the need given in 3GPP TS 33.310.
578
 *
579
 * Returns 1 on success, 0 on error or validation failed.
580
 */
581
int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
582
8.73k
{
583
8.73k
    X509 *scrt;
584
585
8.73k
    ossl_cmp_debug(ctx, "validating CMP message");
586
8.73k
    if (ctx == NULL || msg == NULL
587
8.73k
        || msg->header == NULL || msg->body == NULL) {
588
0
        ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT);
589
0
        return 0;
590
0
    }
591
592
8.73k
    if (msg->header->protectionAlg == NULL /* unprotected message */
593
8.73k
        || msg->protection == NULL || msg->protection->data == NULL) {
594
1.74k
        ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
595
1.74k
        return 0;
596
1.74k
    }
597
598
6.99k
    switch (ossl_cmp_hdr_get_protection_nid(msg->header)) {
599
        /* 5.1.3.1.  Shared Secret Information */
600
2.00k
    case NID_id_PasswordBasedMAC:
601
2.00k
        if (ctx->secretValue == NULL) {
602
973
            ossl_cmp_info(ctx, "no secret available for verifying PBM-based CMP message protection");
603
973
            ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_SECRET);
604
973
            return 0;
605
973
        }
606
1.03k
        if (verify_PBMAC(ctx, msg)) {
607
            /*
608
             * RFC 9810, 5.3.2: 'Note that if the PKI message protection is
609
             * "shared secret information", then any certificate transported in
610
             * the caPubs field may be directly trusted as a root CA
611
             * certificate by the initiator.'
612
             */
613
5
            switch (OSSL_CMP_MSG_get_bodytype(msg)) {
614
0
            case -1:
615
0
                return 0;
616
0
            case OSSL_CMP_PKIBODY_IP:
617
0
            case OSSL_CMP_PKIBODY_CP:
618
0
            case OSSL_CMP_PKIBODY_KUP:
619
2
            case OSSL_CMP_PKIBODY_CCP:
620
2
                if (ctx->trusted != NULL) {
621
0
                    STACK_OF(X509) *certs = msg->body->value.ip->caPubs;
622
                    /* value.ip is same for cp, kup, and ccp */
623
624
0
                    if (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, certs, 0))
625
                        /* adds both self-issued and not self-issued certs */
626
0
                        return 0;
627
0
                }
628
2
                break;
629
3
            default:
630
3
                break;
631
5
            }
632
5
            ossl_cmp_debug(ctx,
633
5
                "successfully validated PBM-based CMP message protection");
634
5
            return 1;
635
5
        }
636
1.02k
        ossl_cmp_warn(ctx, "verifying PBM-based CMP message protection failed");
637
1.02k
        break;
638
639
        /*
640
         * 5.1.3.2 DH Key Pairs
641
         * Not yet supported
642
         */
643
31
    case NID_id_DHBasedMac:
644
31
        ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC);
645
31
        break;
646
647
        /*
648
         * 5.1.3.3.  Signature
649
         */
650
4.95k
    default:
651
4.95k
        scrt = ctx->srvCert;
652
4.95k
        if (scrt == NULL) {
653
4.95k
            if (ctx->trusted == NULL && ctx->secretValue != NULL) {
654
1.99k
                ossl_cmp_info(ctx, "no trust store nor pinned sender cert available for verifying signature-based CMP message protection");
655
1.99k
                ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_TRUST_ANCHOR);
656
1.99k
                return 0;
657
1.99k
            }
658
2.96k
            if (check_msg_find_cert(ctx, msg)) {
659
0
                ossl_cmp_log1(DEBUG, ctx,
660
0
                    "successfully validated signature-based CMP message protection using trust store%s",
661
0
                    ctx->permitTAInExtraCertsForIR ? " or 3GPP mode" : "");
662
0
                return 1;
663
0
            }
664
2.96k
        } else { /* use pinned sender cert */
665
            /* use ctx->srvCert for signature check even if not acceptable */
666
0
            if (verify_signature(ctx, msg, scrt)) {
667
0
                ossl_cmp_debug(ctx,
668
0
                    "successfully validated signature-based CMP message protection using pinned sender cert");
669
0
                return ossl_cmp_ctx_set1_validatedSrvCert(ctx, scrt);
670
0
            }
671
0
            ossl_cmp_warn(ctx, "CMP message signature verification failed");
672
0
            ERR_raise(ERR_LIB_CMP, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG);
673
0
        }
674
2.96k
        break;
675
6.99k
    }
676
4.02k
    return 0;
677
6.99k
}
678
679
static int check_transactionID_or_nonce(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *expected,
680
    const ASN1_OCTET_STRING *actual, int bodytype, int reason)
681
76.1k
{
682
76.1k
    if (expected != NULL
683
0
        && (actual == NULL || ASN1_OCTET_STRING_cmp(expected, actual) != 0)) {
684
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
685
        char *expected_str, *actual_str, *expected_msg, *actual_msg;
686
        const int strict = bodytype != OSSL_CMP_PKIBODY_ERROR || !ctx->nonmatchedErrorNonces;
687
        int res = 0;
688
689
        if (reason == 0) /* at end of polling, overall check is not yet complete */
690
            return res;
691
        expected_str = i2s_ASN1_OCTET_STRING(NULL, expected);
692
        expected_msg = expected_str == NULL ? "?" : expected_str;
693
        actual_str = actual == NULL ? NULL : i2s_ASN1_OCTET_STRING(NULL, actual);
694
        actual_msg = actual == NULL ? "(none)" : actual_str == NULL ? "?"
695
                                                                    : actual_str;
696
        if (strict) {
697
            ERR_raise_data(ERR_LIB_CMP, reason, "expected = %s, actual = %s",
698
                expected_msg, actual_msg);
699
        } else {
700
            ossl_cmp_log3(WARN, ctx, "ignoring missing or non-matching %s of error message, expected = %s, actual = %s",
701
                reason == CMP_R_TRANSACTIONID_UNMATCHED ? "transactionID" : "recipNonce",
702
                expected_msg, actual_msg);
703
            res = 1;
704
        }
705
        OPENSSL_free(expected_str);
706
        OPENSSL_free(actual_str);
707
        return res;
708
#endif
709
0
    }
710
76.1k
    return 1;
711
76.1k
}
712
713
/*-
714
 * Check received message (i.e., response by server or request from client)
715
 * Any msg->extraCerts are prepended to ctx->untrusted.
716
 *
717
 * Ensures that:
718
 * its sender is of appropriate type (currently only X509_NAME) and
719
 *     matches any expected sender or srvCert subject given in the ctx
720
 * it has a valid body type
721
 * its protection is valid (or invalid/absent, but only if a callback function
722
 *     is present and yields a positive result using also the supplied argument)
723
 * its transaction ID matches the previous transaction ID stored in ctx (if any)
724
 * its recipNonce matches the previous senderNonce stored in the ctx (if any)
725
 *
726
 * If everything is fine:
727
 * learns the senderNonce from the received message,
728
 * learns the transaction ID if it is not yet in ctx,
729
 * and makes any certs in caPubs directly trusted.
730
 *
731
 * Returns 1 on success, 0 on error.
732
 */
733
int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
734
    ossl_cmp_allow_unprotected_cb_t cb, int cb_arg)
735
7.63k
{
736
7.63k
    OSSL_CMP_PKIHEADER *hdr;
737
7.63k
    const X509_NAME *expected_sender;
738
7.63k
    int bodytype, end_of_polling;
739
7.63k
    int num_untrusted, num_added, res;
740
741
7.63k
    if (!ossl_assert(ctx != NULL && msg != NULL && msg->header != NULL))
742
0
        return 0;
743
7.63k
    hdr = OSSL_CMP_MSG_get0_header(msg);
744
7.63k
    bodytype = OSSL_CMP_MSG_get_bodytype(msg);
745
746
    /* If expected_sender is given, validate sender name of received msg */
747
7.63k
    expected_sender = ctx->expected_sender;
748
7.63k
    if (expected_sender == NULL && ctx->srvCert != NULL)
749
0
        expected_sender = X509_get_subject_name(ctx->srvCert);
750
7.63k
    if (expected_sender != NULL) {
751
0
        const X509_NAME *actual_sender;
752
0
        char *str;
753
754
0
        if (hdr->sender == NULL) {
755
0
            ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_SENDER_IDENTIFICATION);
756
0
            return 0;
757
0
        }
758
759
0
        if (hdr->sender->type != GEN_DIRNAME) {
760
0
            ERR_raise(ERR_LIB_CMP, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
761
0
            return 0;
762
0
        }
763
0
        actual_sender = hdr->sender->d.directoryName;
764
        /*
765
         * Compare actual sender name of response with expected sender name.
766
         * Mitigates risk of accepting misused PBM secret or
767
         * misused certificate of an unauthorized entity of a trusted hierarchy.
768
         */
769
0
        if (!check_name(ctx, 0, "sender DN field", actual_sender,
770
0
                "expected sender", expected_sender)) {
771
0
            str = X509_NAME_oneline(actual_sender, NULL, 0);
772
0
            ERR_raise_data(ERR_LIB_CMP, CMP_R_UNEXPECTED_SENDER,
773
0
                "%s", str != NULL ? str : "<unknown>");
774
0
            OPENSSL_free(str);
775
0
            return 0;
776
0
        }
777
0
    }
778
779
    /* Ignoring recipient */
780
    /* Note: if recipient was NULL-DN it could be learned here if needed */
781
782
7.63k
    num_added = sk_X509_num(msg->extraCerts);
783
7.63k
    if (num_added > 10)
784
0
        ossl_cmp_log1(WARN, ctx, "received CMP message contains %d extraCerts",
785
7.63k
            num_added);
786
    /*
787
     * Store any provided extraCerts in ctx for use in OSSL_CMP_validate_msg()
788
     * and for future use, such that they are available to ctx->certConf_cb and
789
     * the peer does not need to send them again in the same transaction.
790
     * Note that it does not help validating the message before storing the
791
     * extraCerts because they do not belong to the protected msg part anyway.
792
     * The extraCerts are prepended. Allows simple removal if they shall not be
793
     * cached. Also they get used first, which is likely good for efficiency.
794
     */
795
7.63k
    num_untrusted = ctx->untrusted == NULL ? 0 : sk_X509_num(ctx->untrusted);
796
7.63k
    res = ossl_x509_add_certs_new(&ctx->untrusted, msg->extraCerts,
797
        /* this allows self-signed certs */
798
7.63k
        X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP
799
7.63k
            | X509_ADD_FLAG_PREPEND);
800
7.63k
    num_added = (ctx->untrusted == NULL ? 0 : sk_X509_num(ctx->untrusted))
801
7.63k
        - num_untrusted;
802
7.63k
    if (!res) {
803
0
        while (num_added-- > 0)
804
0
            X509_free(sk_X509_shift(ctx->untrusted));
805
0
        return 0;
806
0
    }
807
808
7.63k
    if (hdr->protectionAlg != NULL)
809
1.13k
        res = OSSL_CMP_validate_msg(ctx, msg)
810
            /* explicitly permitted exceptions for invalid protection: */
811
1.13k
            || (cb != NULL && (*cb)(ctx, msg, 1, cb_arg) > 0);
812
6.50k
    else
813
        /* explicitly permitted exceptions for missing protection: */
814
6.50k
        res = cb != NULL && (*cb)(ctx, msg, 0, cb_arg) > 0;
815
7.63k
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
816
7.63k
    res = 1; /* support more aggressive fuzzing by letting invalid msg pass */
817
7.63k
#endif
818
819
    /*
820
     * remove extraCerts again if not caching
821
     * or if we failed validation above, lest a remote user
822
     * starts sending us lots of certificates in invalid messages
823
     * leading to a DOS from unbounded certificate stack growth
824
     */
825
7.63k
    if (ctx->noCacheExtraCerts || res != 1)
826
0
        while (num_added-- > 0)
827
0
            X509_free(sk_X509_shift(ctx->untrusted));
828
829
7.63k
    if (!res) {
830
0
        if (hdr->protectionAlg != NULL)
831
0
            ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_VALIDATING_PROTECTION);
832
0
        else
833
0
            ERR_raise(ERR_LIB_CMP, CMP_R_MISSING_PROTECTION);
834
0
        return 0;
835
0
    }
836
837
    /* check CMP version number in header */
838
7.63k
    if (ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO_2
839
6.49k
        && ossl_cmp_hdr_get_pvno(hdr) != OSSL_CMP_PVNO_3) {
840
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
841
        ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PVNO);
842
        return 0;
843
#endif
844
6.49k
    }
845
846
7.63k
    if (bodytype < 0) {
847
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
848
        ERR_raise(ERR_LIB_CMP, CMP_R_PKIBODY_ERROR);
849
        return 0;
850
#endif
851
0
    }
852
853
    /* compare received transactionID with the expected one in previous msg */
854
7.63k
    if (!check_transactionID_or_nonce(ctx, ctx->transactionID, hdr->transactionID,
855
7.63k
            bodytype, CMP_R_TRANSACTIONID_UNMATCHED))
856
0
        return 0;
857
858
    /*
859
     * Compare received nonce with the one we sent last.
860
     * When we received the final response at the end of polling,
861
     * we allow also the nonce that we sent earlier with the original request,
862
     * as specified in RFC 9483 section 5.1.5.
863
     */
864
7.63k
    end_of_polling = ctx->first_senderNonce != NULL && bodytype != OSSL_CMP_PKIBODY_POLLREP;
865
7.63k
    if (!check_transactionID_or_nonce(ctx, ctx->senderNonce, hdr->recipNonce,
866
7.63k
            bodytype, end_of_polling ? 0 : CMP_R_RECIPNONCE_UNMATCHED)) {
867
0
        if (!end_of_polling
868
            /* otherwise, compare received nonce with our sender nonce at poll start: */
869
0
            || !check_transactionID_or_nonce(ctx, ctx->first_senderNonce, hdr->recipNonce,
870
0
                bodytype, CMP_R_RECIPNONCE_UNMATCHED))
871
0
            return 0;
872
0
    }
873
874
    /* if not yet present, learn transactionID */
875
7.63k
    if (ctx->transactionID == NULL
876
7.63k
        && !OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID))
877
0
        return 0;
878
879
    /*
880
     * RFC 9810 section 5.1.1 states: the recipNonce is copied from
881
     * the senderNonce of the previous message in the transaction.
882
     * --> Store for setting in next message
883
     */
884
7.63k
    if (!ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce))
885
0
        return 0;
886
887
7.63k
    if (ossl_cmp_hdr_get_protection_nid(hdr) == NID_id_PasswordBasedMAC) {
888
        /*
889
         * RFC 9810, 5.3.2: 'Note that if the PKI message protection is
890
         * "shared secret information", then any certificate transported in
891
         * the caPubs field may be directly trusted as a root CA
892
         * certificate by the initiator.'
893
         */
894
91
        switch (bodytype) {
895
1
        case OSSL_CMP_PKIBODY_IP:
896
4
        case OSSL_CMP_PKIBODY_CP:
897
5
        case OSSL_CMP_PKIBODY_KUP:
898
9
        case OSSL_CMP_PKIBODY_CCP:
899
9
            if (ctx->trusted != NULL) {
900
0
                STACK_OF(X509) *certs = msg->body->value.ip->caPubs;
901
                /* value.ip is same for cp, kup, and ccp */
902
903
0
                if (!ossl_cmp_X509_STORE_add1_certs(ctx->trusted, certs, 0))
904
                    /* adds both self-issued and not self-issued certs */
905
0
                    return 0;
906
0
            }
907
9
            break;
908
82
        default:
909
82
            break;
910
91
        }
911
91
    }
912
7.63k
    return 1;
913
7.63k
}
914
915
int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx,
916
    const OSSL_CMP_MSG *msg, int acceptRAVerified)
917
5.01k
{
918
5.01k
    if (!ossl_assert(msg != NULL && msg->body != NULL))
919
0
        return 0;
920
5.01k
    switch (msg->body->type) {
921
2.82k
    case OSSL_CMP_PKIBODY_P10CR: {
922
2.82k
        X509_REQ *req = msg->body->value.p10cr;
923
924
2.82k
        if (X509_REQ_verify_ex(req, X509_REQ_get0_pubkey(req), ctx->libctx,
925
2.82k
                ctx->propq)
926
2.82k
            <= 0) {
927
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
928
            ERR_raise(ERR_LIB_CMP, CMP_R_REQUEST_NOT_ACCEPTED);
929
            return 0;
930
#endif
931
2.82k
        }
932
2.82k
    } break;
933
1.14k
    case OSSL_CMP_PKIBODY_IR:
934
1.84k
    case OSSL_CMP_PKIBODY_CR:
935
2.18k
    case OSSL_CMP_PKIBODY_KUR:
936
2.18k
        if (!OSSL_CRMF_MSGS_verify_popo(msg->body->value.ir, OSSL_CMP_CERTREQID,
937
2.18k
                acceptRAVerified,
938
2.18k
                ctx->libctx, ctx->propq)) {
939
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
940
            return 0;
941
#endif
942
2.08k
        }
943
2.18k
        break;
944
0
    default:
945
0
        ERR_raise(ERR_LIB_CMP, CMP_R_PKIBODY_ERROR);
946
0
        return 0;
947
5.01k
    }
948
5.01k
    return 1;
949
5.01k
}