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