]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ocsp/ocsp_vfy.c
Fix safestack issues in x509.h
[thirdparty/openssl.git] / crypto / ocsp / ocsp_vfy.c
CommitLineData
0f113f3e 1/*
33388b44 2 * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
9b4dc830 3 *
0c496700 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
b1322259
RS
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
9b4dc830
DSH
8 */
9
10#include <openssl/ocsp.h>
706457b7 11#include "ocsp_local.h"
9b4dc830 12#include <openssl/err.h>
3ebac273 13#include <string.h>
9b4dc830 14
852c2ed2 15DEFINE_STACK_OF(OCSP_ONEREQ)
852c2ed2
RS
16DEFINE_STACK_OF(OCSP_SINGLERESP)
17
0f113f3e 18static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
a773b52a 19 STACK_OF(X509) *certs, unsigned long flags);
9b4dc830 20static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
a773b52a 21static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain);
0f113f3e
MC
22static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp,
23 OCSP_CERTID **ret);
24static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
25 STACK_OF(OCSP_SINGLERESP) *sresp);
a773b52a 26static int ocsp_check_delegated(X509 *x);
0f113f3e 27static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req,
8cc86b81 28 const X509_NAME *nm, STACK_OF(X509) *certs,
a773b52a 29 unsigned long flags);
9b4dc830
DSH
30
31/* Verify a basic response message */
32
33int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
0f113f3e
MC
34 X509_STORE *st, unsigned long flags)
35{
36 X509 *signer, *x;
37 STACK_OF(X509) *chain = NULL;
4ca5efc2 38 STACK_OF(X509) *untrusted = NULL;
f0e0fd51 39 X509_STORE_CTX *ctx = NULL;
0495a3ec 40 X509_VERIFY_PARAM *vp;
a773b52a
RS
41 int i, ret = ocsp_find_signer(&signer, bs, certs, flags);
42
0f113f3e
MC
43 if (!ret) {
44 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,
45 OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
d32f5d87 46 goto end;
f0e0fd51
RS
47 }
48 ctx = X509_STORE_CTX_new();
49 if (ctx == NULL) {
50 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE);
d32f5d87 51 goto f_err;
0f113f3e
MC
52 }
53 if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
54 flags |= OCSP_NOVERIFY;
55 if (!(flags & OCSP_NOSIGS)) {
56 EVP_PKEY *skey;
c51a8af8 57
8382fd3a 58 skey = X509_get0_pubkey(signer);
d32f5d87
RL
59 if (skey == NULL) {
60 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_NO_SIGNER_KEY);
f0e0fd51 61 goto err;
0f113f3e 62 }
d32f5d87
RL
63 ret = OCSP_BASICRESP_verify(bs, skey, 0);
64 if (ret <= 0) {
65 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE);
66 goto end;
67 }
0f113f3e
MC
68 }
69 if (!(flags & OCSP_NOVERIFY)) {
70 int init_res;
eeccc237 71
4ca5efc2
DSH
72 if (flags & OCSP_NOCHAIN) {
73 untrusted = NULL;
74 } else if (bs->certs && certs) {
75 untrusted = sk_X509_dup(bs->certs);
eeccc237
DDO
76 if (!X509_add_certs(untrusted, certs, X509_ADD_FLAG_DEFAULT))
77 goto f_err;
121738d1
DO
78 } else if (certs != NULL) {
79 untrusted = certs;
4ca5efc2
DSH
80 } else {
81 untrusted = bs->certs;
82 }
f0e0fd51 83 init_res = X509_STORE_CTX_init(ctx, st, signer, untrusted);
0f113f3e 84 if (!init_res) {
0f113f3e 85 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB);
d32f5d87 86 goto f_err;
0f113f3e 87 }
0495a3ec
RS
88 if ((flags & OCSP_PARTIAL_CHAIN) != 0
89 && (vp = X509_STORE_CTX_get0_param(ctx)) != NULL)
90 X509_VERIFY_PARAM_set_flags(vp, X509_V_FLAG_PARTIAL_CHAIN);
9b4dc830 91
f0e0fd51
RS
92 X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER);
93 ret = X509_verify_cert(ctx);
94 chain = X509_STORE_CTX_get1_chain(ctx);
0f113f3e 95 if (ret <= 0) {
f0e0fd51 96 i = X509_STORE_CTX_get_error(ctx);
0f113f3e
MC
97 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,
98 OCSP_R_CERTIFICATE_VERIFY_ERROR);
99 ERR_add_error_data(2, "Verify error:",
100 X509_verify_cert_error_string(i));
d32f5d87 101 goto end;
0f113f3e
MC
102 }
103 if (flags & OCSP_NOCHECKS) {
104 ret = 1;
105 goto end;
106 }
107 /*
108 * At this point we have a valid certificate chain need to verify it
109 * against the OCSP issuer criteria.
110 */
a773b52a 111 ret = ocsp_check_issuer(bs, chain);
0f113f3e
MC
112
113 /* If fatal error or valid match then finish */
114 if (ret != 0)
64a1385a 115 goto end;
0f113f3e
MC
116
117 /*
118 * Easy case: explicitly trusted. Get root CA and check for explicit
119 * trust
120 */
121 if (flags & OCSP_NOEXPLICIT)
122 goto end;
123
124 x = sk_X509_value(chain, sk_X509_num(chain) - 1);
125 if (X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED) {
126 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_ROOT_CA_NOT_TRUSTED);
f0e0fd51 127 goto err;
0f113f3e
MC
128 }
129 ret = 1;
130 }
0f113f3e 131 end:
f0e0fd51 132 X509_STORE_CTX_free(ctx);
222561fe 133 sk_X509_pop_free(chain, X509_free);
4ca5efc2
DSH
134 if (bs->certs && certs)
135 sk_X509_free(untrusted);
0f113f3e 136 return ret;
d32f5d87
RL
137
138 err:
139 ret = 0;
140 goto end;
141 f_err:
142 ret = -1;
143 goto end;
0f113f3e
MC
144}
145
ce5886dd 146int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer,
eb48052e 147 STACK_OF(X509) *extra_certs)
ce5886dd
BK
148{
149 int ret;
150
151 ret = ocsp_find_signer(signer, bs, extra_certs, 0);
152 return (ret > 0) ? 1 : 0;
153}
154
0f113f3e 155static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
a773b52a 156 STACK_OF(X509) *certs, unsigned long flags)
0f113f3e
MC
157{
158 X509 *signer;
a332635e 159 OCSP_RESPID *rid = &bs->tbsResponseData.responderId;
c51a8af8 160
0f113f3e
MC
161 if ((signer = ocsp_find_signer_sk(certs, rid))) {
162 *psigner = signer;
163 return 2;
164 }
165 if (!(flags & OCSP_NOINTERN) &&
166 (signer = ocsp_find_signer_sk(bs->certs, rid))) {
167 *psigner = signer;
168 return 1;
169 }
170 /* Maybe lookup from store if by subject name */
171
172 *psigner = NULL;
173 return 0;
174}
9b4dc830
DSH
175
176static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
0f113f3e
MC
177{
178 int i;
179 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
180 X509 *x;
181
182 /* Easy if lookup by name */
183 if (id->type == V_OCSP_RESPID_NAME)
184 return X509_find_by_subject(certs, id->value.byName);
185
186 /* Lookup by key hash */
187
188 /* If key hash isn't SHA1 length then forget it */
189 if (id->value.byKey->length != SHA_DIGEST_LENGTH)
190 return NULL;
191 keyhash = id->value.byKey->data;
192 /* Calculate hash of each key and compare */
193 for (i = 0; i < sk_X509_num(certs); i++) {
194 x = sk_X509_value(certs, i);
c51a8af8
P
195 if (!X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL))
196 break;
197 if (memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH) == 0)
0f113f3e
MC
198 return x;
199 }
200 return NULL;
201}
202
a773b52a 203static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain)
0f113f3e
MC
204{
205 STACK_OF(OCSP_SINGLERESP) *sresp;
206 X509 *signer, *sca;
207 OCSP_CERTID *caid = NULL;
208 int i;
0f113f3e 209
c51a8af8 210 sresp = bs->tbsResponseData.responses;
0f113f3e
MC
211 if (sk_X509_num(chain) <= 0) {
212 OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, OCSP_R_NO_CERTIFICATES_IN_CHAIN);
213 return -1;
214 }
215
216 /* See if the issuer IDs match. */
217 i = ocsp_check_ids(sresp, &caid);
218
219 /* If ID mismatch or other error then return */
220 if (i <= 0)
221 return i;
222
223 signer = sk_X509_value(chain, 0);
224 /* Check to see if OCSP responder CA matches request CA */
225 if (sk_X509_num(chain) > 1) {
226 sca = sk_X509_value(chain, 1);
227 i = ocsp_match_issuerid(sca, caid, sresp);
228 if (i < 0)
229 return i;
230 if (i) {
231 /* We have a match, if extensions OK then success */
a773b52a 232 if (ocsp_check_delegated(signer))
0f113f3e
MC
233 return 1;
234 return 0;
235 }
236 }
237
238 /* Otherwise check if OCSP request signed directly by request CA */
239 return ocsp_match_issuerid(signer, caid, sresp);
240}
241
242/*
243 * Check the issuer certificate IDs for equality. If there is a mismatch with
244 * the same algorithm then there's no point trying to match any certificates
245 * against the issuer. If the issuer IDs all match then we just need to check
246 * equality against one of them.
e8af92fc 247 */
0f113f3e 248
e8af92fc 249static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret)
0f113f3e
MC
250{
251 OCSP_CERTID *tmpid, *cid;
252 int i, idcount;
253
254 idcount = sk_OCSP_SINGLERESP_num(sresp);
255 if (idcount <= 0) {
256 OCSPerr(OCSP_F_OCSP_CHECK_IDS,
257 OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA);
258 return -1;
259 }
260
261 cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId;
262
263 *ret = NULL;
264
265 for (i = 1; i < idcount; i++) {
266 tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
267 /* Check to see if IDs match */
268 if (OCSP_id_issuer_cmp(cid, tmpid)) {
0d4fb843 269 /* If algorithm mismatch let caller deal with it */
a332635e
DSH
270 if (OBJ_cmp(tmpid->hashAlgorithm.algorithm,
271 cid->hashAlgorithm.algorithm))
0f113f3e
MC
272 return 2;
273 /* Else mismatch */
274 return 0;
275 }
276 }
e8af92fc 277
0f113f3e
MC
278 /* All IDs match: only need to check one ID */
279 *ret = cid;
280 return 1;
281}
e8af92fc 282
c51a8af8
P
283/*
284 * Match the certificate issuer ID.
285 * Returns -1 on error, 0 if there is no match and 1 if there is a match.
286 */
e8af92fc 287static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
0f113f3e
MC
288 STACK_OF(OCSP_SINGLERESP) *sresp)
289{
290 /* If only one ID to match then do it */
c51a8af8 291 if (cid != NULL) {
0f113f3e 292 const EVP_MD *dgst;
8cc86b81 293 const X509_NAME *iname;
0f113f3e
MC
294 int mdlen;
295 unsigned char md[EVP_MAX_MD_SIZE];
c51a8af8
P
296
297 dgst = EVP_get_digestbyobj(cid->hashAlgorithm.algorithm);
298 if (dgst == NULL) {
299 OCSPerr(0, OCSP_R_UNKNOWN_MESSAGE_DIGEST);
0f113f3e
MC
300 return -1;
301 }
302
303 mdlen = EVP_MD_size(dgst);
c51a8af8
P
304 if (mdlen < 0) {
305 OCSPerr(0, OCSP_R_DIGEST_SIZE_ERR);
0f113f3e 306 return -1;
c51a8af8
P
307 }
308 if (cid->issuerNameHash.length != mdlen ||
309 cid->issuerKeyHash.length != mdlen)
0f113f3e
MC
310 return 0;
311 iname = X509_get_subject_name(cert);
c51a8af8
P
312 if (!X509_NAME_digest(iname, dgst, md, NULL)) {
313 OCSPerr(0, OCSP_R_DIGEST_NAME_ERR);
0f113f3e 314 return -1;
c51a8af8
P
315 }
316 if (memcmp(md, cid->issuerNameHash.data, mdlen) != 0)
0f113f3e 317 return 0;
c51a8af8
P
318 if (!X509_pubkey_digest(cert, dgst, md, NULL)) {
319 OCSPerr(0, OCSP_R_DIGEST_ERR);
320 return -1;
321 }
322 if (memcmp(md, cid->issuerKeyHash.data, mdlen) != 0)
0f113f3e 323 return 0;
0f113f3e
MC
324 } else {
325 /* We have to match the whole lot */
326 int i, ret;
327 OCSP_CERTID *tmpid;
c51a8af8 328
0f113f3e
MC
329 for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) {
330 tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId;
331 ret = ocsp_match_issuerid(cert, tmpid, NULL);
332 if (ret <= 0)
333 return ret;
334 }
0f113f3e 335 }
c51a8af8 336 return 1;
0f113f3e 337}
e8af92fc 338
a773b52a 339static int ocsp_check_delegated(X509 *x)
0f113f3e 340{
a8d8e06b
DSH
341 if ((X509_get_extension_flags(x) & EXFLAG_XKUSAGE)
342 && (X509_get_extended_key_usage(x) & XKU_OCSP_SIGN))
0f113f3e
MC
343 return 1;
344 OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE);
345 return 0;
346}
347
348/*
349 * Verify an OCSP request. This is fortunately much easier than OCSP response
350 * verify. Just find the signers certificate and verify it against a given
351 * trust value.
fafc7f98
DSH
352 */
353
0f113f3e
MC
354int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
355 X509_STORE *store, unsigned long flags)
356{
357 X509 *signer;
8cc86b81 358 const X509_NAME *nm;
0f113f3e 359 GENERAL_NAME *gen;
f0e0fd51
RS
360 int ret = 0;
361 X509_STORE_CTX *ctx = X509_STORE_CTX_new();
362
363 if (ctx == NULL) {
364 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_MALLOC_FAILURE);
365 goto err;
366 }
367
0f113f3e
MC
368 if (!req->optionalSignature) {
369 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED);
f0e0fd51 370 goto err;
0f113f3e 371 }
a332635e 372 gen = req->tbsRequest.requestorName;
0f113f3e
MC
373 if (!gen || gen->type != GEN_DIRNAME) {
374 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
375 OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
f0e0fd51 376 goto err;
0f113f3e
MC
377 }
378 nm = gen->d.directoryName;
a773b52a 379 ret = ocsp_req_find_signer(&signer, req, nm, certs, flags);
0f113f3e
MC
380 if (ret <= 0) {
381 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
382 OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
f0e0fd51 383 goto err;
0f113f3e
MC
384 }
385 if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
386 flags |= OCSP_NOVERIFY;
387 if (!(flags & OCSP_NOSIGS)) {
388 EVP_PKEY *skey;
8382fd3a 389 skey = X509_get0_pubkey(signer);
0f113f3e 390 ret = OCSP_REQUEST_verify(req, skey);
0f113f3e
MC
391 if (ret <= 0) {
392 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE);
f0e0fd51 393 goto err;
0f113f3e
MC
394 }
395 }
396 if (!(flags & OCSP_NOVERIFY)) {
397 int init_res;
c51a8af8 398
0f113f3e 399 if (flags & OCSP_NOCHAIN)
f0e0fd51 400 init_res = X509_STORE_CTX_init(ctx, store, signer, NULL);
0f113f3e 401 else
f0e0fd51 402 init_res = X509_STORE_CTX_init(ctx, store, signer,
0f113f3e
MC
403 req->optionalSignature->certs);
404 if (!init_res) {
405 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_X509_LIB);
f0e0fd51 406 goto err;
fafc7f98
DSH
407 }
408
f0e0fd51
RS
409 X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER);
410 X509_STORE_CTX_set_trust(ctx, X509_TRUST_OCSP_REQUEST);
411 ret = X509_verify_cert(ctx);
0f113f3e 412 if (ret <= 0) {
f0e0fd51 413 ret = X509_STORE_CTX_get_error(ctx);
0f113f3e
MC
414 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
415 OCSP_R_CERTIFICATE_VERIFY_ERROR);
416 ERR_add_error_data(2, "Verify error:",
417 X509_verify_cert_error_string(ret));
f0e0fd51 418 goto err;
0f113f3e
MC
419 }
420 }
f0e0fd51
RS
421 ret = 1;
422 goto end;
423
424err:
425 ret = 0;
426end:
427 X509_STORE_CTX_free(ctx);
428 return ret;
429
0f113f3e
MC
430}
431
432static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req,
8cc86b81 433 const X509_NAME *nm, STACK_OF(X509) *certs,
a773b52a 434 unsigned long flags)
0f113f3e
MC
435{
436 X509 *signer;
c51a8af8 437
0f113f3e
MC
438 if (!(flags & OCSP_NOINTERN)) {
439 signer = X509_find_by_subject(req->optionalSignature->certs, nm);
440 if (signer) {
441 *psigner = signer;
442 return 1;
443 }
444 }
445
446 signer = X509_find_by_subject(certs, nm);
447 if (signer) {
448 *psigner = signer;
449 return 2;
450 }
451 return 0;
452}