Bug Summary

File:src/lib/libcrypto/ocsp/ocsp_cl.c
Warning:line 161, column 33
Although the value stored to 'sig' is used in the enclosing expression, the value is never actually read from 'sig'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ocsp_cl.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libcrypto/obj -resource-dir /usr/local/lib/clang/13.0.0 -D LIBRESSL_INTERNAL -D LIBRESSL_CRYPTO_INTERNAL -D DSO_DLFCN -D HAVE_DLFCN_H -D HAVE_FUNOPEN -D OPENSSL_NO_HW_PADLOCK -I /usr/src/lib/libcrypto -I /usr/src/lib/libcrypto/asn1 -I /usr/src/lib/libcrypto/bio -I /usr/src/lib/libcrypto/bn -I /usr/src/lib/libcrypto/bytestring -I /usr/src/lib/libcrypto/dh -I /usr/src/lib/libcrypto/dsa -I /usr/src/lib/libcrypto/ec -I /usr/src/lib/libcrypto/ecdh -I /usr/src/lib/libcrypto/ecdsa -I /usr/src/lib/libcrypto/evp -I /usr/src/lib/libcrypto/hmac -I /usr/src/lib/libcrypto/modes -I /usr/src/lib/libcrypto/ocsp -I /usr/src/lib/libcrypto/rsa -I /usr/src/lib/libcrypto/x509 -I /usr/src/lib/libcrypto/obj -D AES_ASM -D BSAES_ASM -D VPAES_ASM -D OPENSSL_IA32_SSE2 -D RSA_ASM -D OPENSSL_BN_ASM_MONT -D OPENSSL_BN_ASM_MONT5 -D OPENSSL_BN_ASM_GF2m -D MD5_ASM -D GHASH_ASM -D RC4_MD5_ASM -D SHA1_ASM -D SHA256_ASM -D SHA512_ASM -D WHIRLPOOL_ASM -D OPENSSL_CPUID_OBJ -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcrypto/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libcrypto/ocsp/ocsp_cl.c
1/* $OpenBSD: ocsp_cl.c,v 1.21 2022/01/07 09:45:52 tb Exp $ */
2/* Written by Tom Titchener <Tom_Titchener@groove.net> for the OpenSSL
3 * project. */
4
5/* History:
6 This file was transfered to Richard Levitte from CertCo by Kathy
7 Weinhold in mid-spring 2000 to be included in OpenSSL or released
8 as a patch kit. */
9
10/* ====================================================================
11 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in
22 * the documentation and/or other materials provided with the
23 * distribution.
24 *
25 * 3. All advertising materials mentioning features or use of this
26 * software must display the following acknowledgment:
27 * "This product includes software developed by the OpenSSL Project
28 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
29 *
30 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
31 * endorse or promote products derived from this software without
32 * prior written permission. For written permission, please contact
33 * openssl-core@openssl.org.
34 *
35 * 5. Products derived from this software may not be called "OpenSSL"
36 * nor may "OpenSSL" appear in their names without prior written
37 * permission of the OpenSSL Project.
38 *
39 * 6. Redistributions of any form whatsoever must retain the following
40 * acknowledgment:
41 * "This product includes software developed by the OpenSSL Project
42 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
45 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
48 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55 * OF THE POSSIBILITY OF SUCH DAMAGE.
56 * ====================================================================
57 *
58 * This product includes cryptographic software written by Eric Young
59 * (eay@cryptsoft.com). This product includes software written by Tim
60 * Hudson (tjh@cryptsoft.com).
61 *
62 */
63
64#include <stdio.h>
65#include <time.h>
66
67#include <openssl/err.h>
68#include <openssl/ocsp.h>
69#include <openssl/objects.h>
70#include <openssl/pem.h>
71#include <openssl/x509.h>
72#include <openssl/x509v3.h>
73
74#include "ocsp_local.h"
75
76/* Utility functions related to sending OCSP requests and extracting
77 * relevant information from the response.
78 */
79
80/* Add an OCSP_CERTID to an OCSP request. Return new OCSP_ONEREQ
81 * pointer: useful if we want to add extensions.
82 */
83OCSP_ONEREQ *
84OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid)
85{
86 OCSP_ONEREQ *one;
87
88 if ((one = OCSP_ONEREQ_new()) == NULL((void*)0))
89 goto err;
90 if (req != NULL((void*)0)) {
91 if (!sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one)sk_push(((_STACK*) (1 ? (req->tbsRequest->requestList) :
(struct stack_st_OCSP_ONEREQ*)0)), ((void*) (1 ? (one) : (OCSP_ONEREQ
*)0)))
)
92 goto err;
93 }
94 OCSP_CERTID_free(one->reqCert);
95 one->reqCert = cid;
96 return one;
97
98 err:
99 OCSP_ONEREQ_free(one);
100 return NULL((void*)0);
101}
102
103/* Set requestorName from an X509_NAME structure */
104int
105OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm)
106{
107 GENERAL_NAME *gen;
108
109 gen = GENERAL_NAME_new();
110 if (gen == NULL((void*)0))
111 return 0;
112 if (!X509_NAME_set(&gen->d.directoryName, nm)) {
113 GENERAL_NAME_free(gen);
114 return 0;
115 }
116 gen->type = GEN_DIRNAME4;
117 if (req->tbsRequest->requestorName)
118 GENERAL_NAME_free(req->tbsRequest->requestorName);
119 req->tbsRequest->requestorName = gen;
120 return 1;
121}
122
123/* Add a certificate to an OCSP request */
124int
125OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert)
126{
127 OCSP_SIGNATURE *sig;
128
129 if (!req->optionalSignature)
130 req->optionalSignature = OCSP_SIGNATURE_new();
131 sig = req->optionalSignature;
132 if (!sig)
133 return 0;
134 if (!cert)
135 return 1;
136 if (!sig->certs && !(sig->certs = sk_X509_new_null()((struct stack_st_X509 *)sk_new_null())))
137 return 0;
138
139 if (!sk_X509_push(sig->certs, cert)sk_push(((_STACK*) (1 ? (sig->certs) : (struct stack_st_X509
*)0)), ((void*) (1 ? (cert) : (X509*)0)))
)
140 return 0;
141 X509_up_ref(cert);
142 return 1;
143}
144
145/* Sign an OCSP request set the requestorName to the subject
146 * name of an optional signers certificate and include one
147 * or more optional certificates in the request. Behaves
148 * like PKCS7_sign().
149 */
150int
151OCSP_request_sign(OCSP_REQUEST *req, X509 *signer, EVP_PKEY *key,
152 const EVP_MD *dgst, STACK_OF(X509)struct stack_st_X509 *certs, unsigned long flags)
153{
154 int i;
155 OCSP_SIGNATURE *sig;
156 X509 *x;
157
158 if (!OCSP_request_set1_name(req, X509_get_subject_name(signer)))
159 goto err;
160
161 if (!(req->optionalSignature = sig = OCSP_SIGNATURE_new()))
Although the value stored to 'sig' is used in the enclosing expression, the value is never actually read from 'sig'
162 goto err;
163 if (key) {
164 if (!X509_check_private_key(signer, key)) {
165 OCSPerror(OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE)ERR_put_error(39,(0xfff),(110),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,165)
;
166 goto err;
167 }
168 if (!OCSP_REQUEST_sign(req, key, dgst)ASN1_item_sign(&OCSP_REQINFO_it, req->optionalSignature
->signatureAlgorithm,((void*)0), req->optionalSignature
->signature,req->tbsRequest,key,dgst)
)
169 goto err;
170 }
171
172 if (!(flags & OCSP_NOCERTS0x1)) {
173 if (!OCSP_request_add1_cert(req, signer))
174 goto err;
175 for (i = 0; i < sk_X509_num(certs)sk_num(((_STACK*) (1 ? (certs) : (struct stack_st_X509*)0))); i++) {
176 x = sk_X509_value(certs, i)((X509 *)sk_value(((_STACK*) (1 ? (certs) : (struct stack_st_X509
*)0)), (i)))
;
177 if (!OCSP_request_add1_cert(req, x))
178 goto err;
179 }
180 }
181
182 return 1;
183
184err:
185 OCSP_SIGNATURE_free(req->optionalSignature);
186 req->optionalSignature = NULL((void*)0);
187 return 0;
188}
189
190/* Get response status */
191int
192OCSP_response_status(OCSP_RESPONSE *resp)
193{
194 return ASN1_ENUMERATED_get(resp->responseStatus);
195}
196
197/* Extract basic response from OCSP_RESPONSE or NULL if
198 * no basic response present.
199 */
200OCSP_BASICRESP *
201OCSP_response_get1_basic(OCSP_RESPONSE *resp)
202{
203 OCSP_RESPBYTES *rb;
204
205 rb = resp->responseBytes;
206 if (!rb) {
207 OCSPerror(OCSP_R_NO_RESPONSE_DATA)ERR_put_error(39,(0xfff),(108),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,207)
;
208 return NULL((void*)0);
209 }
210 if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic365) {
211 OCSPerror(OCSP_R_NOT_BASIC_RESPONSE)ERR_put_error(39,(0xfff),(104),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,211)
;
212 return NULL((void*)0);
213 }
214
215 return ASN1_item_unpack(rb->response, &OCSP_BASICRESP_it);
216}
217
218/* Return number of OCSP_SINGLERESP reponses present in
219 * a basic response.
220 */
221int
222OCSP_resp_count(OCSP_BASICRESP *bs)
223{
224 if (!bs)
225 return -1;
226 return sk_OCSP_SINGLERESP_num(bs->tbsResponseData->responses)sk_num(((_STACK*) (1 ? (bs->tbsResponseData->responses)
: (struct stack_st_OCSP_SINGLERESP*)0)))
;
227}
228
229/* Extract an OCSP_SINGLERESP response with a given index */
230OCSP_SINGLERESP *
231OCSP_resp_get0(OCSP_BASICRESP *bs, int idx)
232{
233 if (!bs)
234 return NULL((void*)0);
235 return sk_OCSP_SINGLERESP_value(bs->tbsResponseData->responses, idx)((OCSP_SINGLERESP *)sk_value(((_STACK*) (1 ? (bs->tbsResponseData
->responses) : (struct stack_st_OCSP_SINGLERESP*)0)), (idx
)))
;
236}
237
238const ASN1_GENERALIZEDTIME *
239OCSP_resp_get0_produced_at(const OCSP_BASICRESP *bs)
240{
241 return bs->tbsResponseData->producedAt;
242}
243
244const STACK_OF(X509)struct stack_st_X509 *
245OCSP_resp_get0_certs(const OCSP_BASICRESP *bs)
246{
247 return bs->certs;
248}
249
250int
251OCSP_resp_get0_id(const OCSP_BASICRESP *bs, const ASN1_OCTET_STRING **pid,
252 const X509_NAME **pname)
253{
254 const OCSP_RESPID *rid = bs->tbsResponseData->responderId;
255
256 if (rid->type == V_OCSP_RESPID_NAME0) {
257 *pname = rid->value.byName;
258 *pid = NULL((void*)0);
259 } else if (rid->type == V_OCSP_RESPID_KEY1) {
260 *pid = rid->value.byKey;
261 *pname = NULL((void*)0);
262 } else {
263 return 0;
264 }
265
266 return 1;
267}
268
269const ASN1_OCTET_STRING *
270OCSP_resp_get0_signature(const OCSP_BASICRESP *bs)
271{
272 return bs->signature;
273}
274
275const X509_ALGOR *
276OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs)
277{
278 return bs->signatureAlgorithm;
279}
280
281const OCSP_RESPDATA *
282OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs)
283{
284 return bs->tbsResponseData;
285}
286
287/* Look single response matching a given certificate ID */
288int
289OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last)
290{
291 int i;
292 STACK_OF(OCSP_SINGLERESP)struct stack_st_OCSP_SINGLERESP *sresp;
293 OCSP_SINGLERESP *single;
294
295 if (!bs)
296 return -1;
297 if (last < 0)
298 last = 0;
299 else
300 last++;
301 sresp = bs->tbsResponseData->responses;
302 for (i = last; i < sk_OCSP_SINGLERESP_num(sresp)sk_num(((_STACK*) (1 ? (sresp) : (struct stack_st_OCSP_SINGLERESP
*)0)))
; i++) {
303 single = sk_OCSP_SINGLERESP_value(sresp, i)((OCSP_SINGLERESP *)sk_value(((_STACK*) (1 ? (sresp) : (struct
stack_st_OCSP_SINGLERESP*)0)), (i)))
;
304 if (!OCSP_id_cmp(id, single->certId))
305 return i;
306 }
307 return -1;
308}
309
310/* Extract status information from an OCSP_SINGLERESP structure.
311 * Note: the revtime and reason values are only set if the
312 * certificate status is revoked. Returns numerical value of
313 * status.
314 */
315int
316OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
317 ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd,
318 ASN1_GENERALIZEDTIME **nextupd)
319{
320 int ret;
321 OCSP_CERTSTATUS *cst;
322
323 if (!single)
324 return -1;
325 cst = single->certStatus;
326 ret = cst->type;
327 if (ret == V_OCSP_CERTSTATUS_REVOKED1) {
328 OCSP_REVOKEDINFO *rev = cst->value.revoked;
329
330 if (revtime)
331 *revtime = rev->revocationTime;
332 if (reason) {
333 if (rev->revocationReason)
334 *reason = ASN1_ENUMERATED_get(
335 rev->revocationReason);
336 else
337 *reason = -1;
338 }
339 }
340 if (thisupd)
341 *thisupd = single->thisUpdate;
342 if (nextupd)
343 *nextupd = single->nextUpdate;
344 return ret;
345}
346
347/* This function combines the previous ones: look up a certificate ID and
348 * if found extract status information. Return 0 is successful.
349 */
350int
351OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
352 int *reason, ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd,
353 ASN1_GENERALIZEDTIME **nextupd)
354{
355 int i;
356 OCSP_SINGLERESP *single;
357
358 i = OCSP_resp_find(bs, id, -1);
359 /* Maybe check for multiple responses and give an error? */
360 if (i < 0)
361 return 0;
362 single = OCSP_resp_get0(bs, i);
363 i = OCSP_single_get0_status(single, reason, revtime, thisupd, nextupd);
364 if (status)
365 *status = i;
366 return 1;
367}
368
369/* Check validity of thisUpdate and nextUpdate fields. It is possible that the request will
370 * take a few seconds to process and/or the time wont be totally accurate. Therefore to avoid
371 * rejecting otherwise valid time we allow the times to be within 'nsec' of the current time.
372 * Also to avoid accepting very old responses without a nextUpdate field an optional maxage
373 * parameter specifies the maximum age the thisUpdate field can be.
374 */
375int
376OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
377 ASN1_GENERALIZEDTIME *nextupd, long nsec, long maxsec)
378{
379 time_t t_now, t_tmp;
380 struct tm tm_this, tm_next, tm_tmp;
381
382 time(&t_now);
383
384 /*
385 * Times must explicitly be a GENERALIZEDTIME as per section
386 * 4.2.2.1 of RFC 6960 - It is invalid to accept other times
387 * (such as UTCTIME permitted/required by RFC 5280 for certificates)
388 */
389
390 /* Check thisUpdate is valid and not more than nsec in the future */
391 if (ASN1_time_parse(thisupd->data, thisupd->length, &tm_this,
392 V_ASN1_GENERALIZEDTIME24) != V_ASN1_GENERALIZEDTIME24) {
393 OCSPerror(OCSP_R_ERROR_IN_THISUPDATE_FIELD)ERR_put_error(39,(0xfff),(123),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,393)
;
394 return 0;
395 } else {
396 t_tmp = t_now + nsec;
397 if (gmtime_r(&t_tmp, &tm_tmp) == NULL((void*)0))
398 return 0;
399 if (ASN1_time_tm_cmp(&tm_this, &tm_tmp) > 0) {
400 OCSPerror(OCSP_R_STATUS_NOT_YET_VALID)ERR_put_error(39,(0xfff),(126),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,400)
;
401 return 0;
402 }
403
404 /*
405 * If maxsec specified check thisUpdate is not more than maxsec
406 * in the past
407 */
408 if (maxsec >= 0) {
409 t_tmp = t_now - maxsec;
410 if (gmtime_r(&t_tmp, &tm_tmp) == NULL((void*)0))
411 return 0;
412 if (ASN1_time_tm_cmp(&tm_this, &tm_tmp) < 0) {
413 OCSPerror(OCSP_R_STATUS_TOO_OLD)ERR_put_error(39,(0xfff),(127),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,413)
;
414 return 0;
415 }
416 }
417 }
418
419 if (!nextupd)
420 return 1;
421
422 /* Check nextUpdate is valid and not more than nsec in the past */
423 if (ASN1_time_parse(nextupd->data, nextupd->length, &tm_next,
424 V_ASN1_GENERALIZEDTIME24) != V_ASN1_GENERALIZEDTIME24) {
425 OCSPerror(OCSP_R_ERROR_IN_NEXTUPDATE_FIELD)ERR_put_error(39,(0xfff),(122),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,425)
;
426 return 0;
427 } else {
428 t_tmp = t_now - nsec;
429 if (gmtime_r(&t_tmp, &tm_tmp) == NULL((void*)0))
430 return 0;
431 if (ASN1_time_tm_cmp(&tm_next, &tm_tmp) < 0) {
432 OCSPerror(OCSP_R_STATUS_EXPIRED)ERR_put_error(39,(0xfff),(125),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,432)
;
433 return 0;
434 }
435 }
436
437 /* Also don't allow nextUpdate to precede thisUpdate */
438 if (ASN1_time_tm_cmp(&tm_next, &tm_this) < 0) {
439 OCSPerror(OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE)ERR_put_error(39,(0xfff),(124),"/usr/src/lib/libcrypto/ocsp/ocsp_cl.c"
,439)
;
440 return 0;
441 }
442
443 return 1;
444}
445
446const OCSP_CERTID *
447OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single)
448{
449 return single->certId;
450}