Bug Summary

File:src/lib/libcrypto/ts/ts_rsp_verify.c
Warning:line 205, column 10
Although the value stored to 'i' is used in the enclosing expression, the value is never actually read from 'i'

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 ts_rsp_verify.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/ts/ts_rsp_verify.c
1/* $OpenBSD: ts_rsp_verify.c,v 1.24 2021/12/12 21:30:14 tb Exp $ */
2/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
3 * project 2002.
4 */
5/* ====================================================================
6 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <stdio.h>
60#include <string.h>
61
62#include <openssl/err.h>
63#include <openssl/objects.h>
64#include <openssl/pkcs7.h>
65#include <openssl/ts.h>
66
67#include "evp_locl.h"
68#include "x509_lcl.h"
69
70/* Private function declarations. */
71
72static int TS_verify_cert(X509_STORE *store, STACK_OF(X509)struct stack_st_X509 *untrusted,
73 X509 *signer, STACK_OF(X509)struct stack_st_X509 **chain);
74static int TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509)struct stack_st_X509 *chain);
75static ESS_SIGNING_CERT *ESS_get_signing_cert(PKCS7_SIGNER_INFO *si);
76static int TS_find_cert(STACK_OF(ESS_CERT_ID)struct stack_st_ESS_CERT_ID *cert_ids, X509 *cert);
77static int TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509_CINF *cinfo);
78static int int_TS_RESP_verify_token(TS_VERIFY_CTX *ctx,
79 PKCS7 *token, TS_TST_INFO *tst_info);
80static int TS_check_status_info(TS_RESP *response);
81static char *TS_get_status_text(STACK_OF(ASN1_UTF8STRING)struct stack_st_ASN1_UTF8STRING *text);
82static int TS_check_policy(ASN1_OBJECT *req_oid, TS_TST_INFO *tst_info);
83static int TS_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
84 X509_ALGOR **md_alg,
85 unsigned char **imprint, unsigned *imprint_len);
86static int TS_check_imprints(X509_ALGOR *algor_a,
87 unsigned char *imprint_a, unsigned len_a,
88 TS_TST_INFO *tst_info);
89static int TS_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info);
90static int TS_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer);
91static int TS_find_name(STACK_OF(GENERAL_NAME)struct stack_st_GENERAL_NAME *gen_names, GENERAL_NAME *name);
92
93/*
94 * Local mapping between response codes and descriptions.
95 * Don't forget to change TS_STATUS_BUF_SIZE when modifying
96 * the elements of this array.
97 */
98static const char *TS_status_text[] = {
99 "granted",
100 "grantedWithMods",
101 "rejection",
102 "waiting",
103 "revocationWarning",
104 "revocationNotification"
105};
106
107#define TS_STATUS_TEXT_SIZE(sizeof(TS_status_text)/sizeof(*TS_status_text)) (sizeof(TS_status_text)/sizeof(*TS_status_text))
108
109/*
110 * This must be greater or equal to the sum of the strings in TS_status_text
111 * plus the number of its elements.
112 */
113#define TS_STATUS_BUF_SIZE256 256
114
115static struct {
116 int code;
117 const char *text;
118} TS_failure_info[] = {
119 { TS_INFO_BAD_ALG0, "badAlg" },
120 { TS_INFO_BAD_REQUEST2, "badRequest" },
121 { TS_INFO_BAD_DATA_FORMAT5, "badDataFormat" },
122 { TS_INFO_TIME_NOT_AVAILABLE14, "timeNotAvailable" },
123 { TS_INFO_UNACCEPTED_POLICY15, "unacceptedPolicy" },
124 { TS_INFO_UNACCEPTED_EXTENSION16, "unacceptedExtension" },
125 { TS_INFO_ADD_INFO_NOT_AVAILABLE17, "addInfoNotAvailable" },
126 { TS_INFO_SYSTEM_FAILURE25, "systemFailure" }
127};
128
129#define TS_FAILURE_INFO_SIZE(sizeof(TS_failure_info) / sizeof(*TS_failure_info)) (sizeof(TS_failure_info) / \
130 sizeof(*TS_failure_info))
131
132/* Functions for verifying a signed TS_TST_INFO structure. */
133
134/*
135 * This function carries out the following tasks:
136 * - Checks if there is one and only one signer.
137 * - Search for the signing certificate in 'certs' and in the response.
138 * - Check the extended key usage and key usage fields of the signer
139 * certificate (done by the path validation).
140 * - Build and validate the certificate path.
141 * - Check if the certificate path meets the requirements of the
142 * SigningCertificate ESS signed attribute.
143 * - Verify the signature value.
144 * - Returns the signer certificate in 'signer', if 'signer' is not NULL.
145 */
146int
147TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509)struct stack_st_X509 *certs,
148 X509_STORE *store, X509 **signer_out)
149{
150 STACK_OF(PKCS7_SIGNER_INFO)struct stack_st_PKCS7_SIGNER_INFO *sinfos = NULL((void*)0);
151 PKCS7_SIGNER_INFO *si;
152 STACK_OF(X509)struct stack_st_X509 *signers = NULL((void*)0);
153 X509 *signer;
154 STACK_OF(X509)struct stack_st_X509 *chain = NULL((void*)0);
155 char buf[4096];
156 int i, j = 0, ret = 0;
157 BIO *p7bio = NULL((void*)0);
158
159 /* Some sanity checks first. */
160 if (!token) {
161 TSerror(TS_R_INVALID_NULL_POINTER)ERR_put_error(47,(0xfff),(102),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,161)
;
162 goto err;
163 }
164
165 /* Check for the correct content type */
166 if (!PKCS7_type_is_signed(token)(OBJ_obj2nid((token)->type) == 22)) {
167 TSerror(TS_R_WRONG_CONTENT_TYPE)ERR_put_error(47,(0xfff),(114),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,167)
;
168 goto err;
169 }
170
171 /* Check if there is one and only one signer. */
172 sinfos = PKCS7_get_signer_info(token);
173 if (!sinfos || sk_PKCS7_SIGNER_INFO_num(sinfos)sk_num(((_STACK*) (1 ? (sinfos) : (struct stack_st_PKCS7_SIGNER_INFO
*)0)))
!= 1) {
174 TSerror(TS_R_THERE_MUST_BE_ONE_SIGNER)ERR_put_error(47,(0xfff),(110),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,174)
;
175 goto err;
176 }
177 si = sk_PKCS7_SIGNER_INFO_value(sinfos, 0)((PKCS7_SIGNER_INFO *)sk_value(((_STACK*) (1 ? (sinfos) : (struct
stack_st_PKCS7_SIGNER_INFO*)0)), (0)))
;
178
179 /* Check for no content: no data to verify signature. */
180 if (PKCS7_get_detached(token)PKCS7_ctrl(token,2,0,((void*)0))) {
181 TSerror(TS_R_NO_CONTENT)ERR_put_error(47,(0xfff),(106),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,181)
;
182 goto err;
183 }
184
185 /* Get hold of the signer certificate, search only internal
186 certificates if it was requested. */
187 signers = PKCS7_get0_signers(token, certs, 0);
188 if (!signers || sk_X509_num(signers)sk_num(((_STACK*) (1 ? (signers) : (struct stack_st_X509*)0))
)
!= 1)
189 goto err;
190 signer = sk_X509_value(signers, 0)((X509 *)sk_value(((_STACK*) (1 ? (signers) : (struct stack_st_X509
*)0)), (0)))
;
191
192 /* Now verify the certificate. */
193 if (!TS_verify_cert(store, certs, signer, &chain))
194 goto err;
195
196 /* Check if the signer certificate is consistent with the
197 ESS extension. */
198 if (!TS_check_signing_certs(si, chain))
199 goto err;
200
201 /* Creating the message digest. */
202 p7bio = PKCS7_dataInit(token, NULL((void*)0));
203
204 /* We now have to 'read' from p7bio to calculate digests etc. */
205 while ((i = BIO_read(p7bio, buf, sizeof(buf))) > 0)
Although the value stored to 'i' is used in the enclosing expression, the value is never actually read from 'i'
206 ;
207
208 /* Verifying the signature. */
209 j = PKCS7_signatureVerify(p7bio, token, si, signer);
210 if (j <= 0) {
211 TSerror(TS_R_SIGNATURE_FAILURE)ERR_put_error(47,(0xfff),(109),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,211)
;
212 goto err;
213 }
214
215 /* Return the signer certificate if needed. */
216 if (signer_out) {
217 *signer_out = signer;
218 CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509)CRYPTO_add_lock(&signer->references,1,3,((void*)0),0);
219 }
220
221 ret = 1;
222
223err:
224 BIO_free_all(p7bio);
225 sk_X509_pop_free(chain, X509_free)sk_pop_free(((_STACK*) (1 ? (chain) : (struct stack_st_X509*)
0)), ((void (*)(void *)) ((1 ? (X509_free) : (void (*)(X509 *
))0))))
;
226 sk_X509_free(signers)sk_free(((_STACK*) (1 ? (signers) : (struct stack_st_X509*)0)
))
;
227
228 return ret;
229}
230
231/*
232 * The certificate chain is returned in chain. Caller is responsible for
233 * freeing the vector.
234 */
235static int
236TS_verify_cert(X509_STORE *store, STACK_OF(X509)struct stack_st_X509 *untrusted, X509 *signer,
237 STACK_OF(X509)struct stack_st_X509 **chain)
238{
239 X509_STORE_CTX cert_ctx;
240 int i;
241 int ret = 0;
242
243 /* chain is an out argument. */
244 *chain = NULL((void*)0);
245 if (X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted) == 0) {
246 TSerror(ERR_R_X509_LIB)ERR_put_error(47,(0xfff),(11),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,246)
;
247 goto err;
248 }
249 if (X509_STORE_CTX_set_purpose(&cert_ctx,
250 X509_PURPOSE_TIMESTAMP_SIGN9) == 0)
251 goto err;
252 i = X509_verify_cert(&cert_ctx);
253 if (i <= 0) {
254 int j = X509_STORE_CTX_get_error(&cert_ctx);
255
256 TSerror(TS_R_CERTIFICATE_VERIFY_ERROR)ERR_put_error(47,(0xfff),(100),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,256)
;
257 ERR_asprintf_error_data("Verify error:%s",
258 X509_verify_cert_error_string(j));
259 goto err;
260 } else {
261 /* Get a copy of the certificate chain. */
262 *chain = X509_STORE_CTX_get1_chain(&cert_ctx);
263 ret = 1;
264 }
265
266err:
267 X509_STORE_CTX_cleanup(&cert_ctx);
268
269 return ret;
270}
271
272static int
273TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509)struct stack_st_X509 *chain)
274{
275 ESS_SIGNING_CERT *ss = ESS_get_signing_cert(si);
276 STACK_OF(ESS_CERT_ID)struct stack_st_ESS_CERT_ID *cert_ids = NULL((void*)0);
277 X509 *cert;
278 int i = 0;
279 int ret = 0;
280
281 if (!ss)
282 goto err;
283 cert_ids = ss->cert_ids;
284 /* The signer certificate must be the first in cert_ids. */
285 cert = sk_X509_value(chain, 0)((X509 *)sk_value(((_STACK*) (1 ? (chain) : (struct stack_st_X509
*)0)), (0)))
;
286 if (TS_find_cert(cert_ids, cert) != 0)
287 goto err;
288
289 /* Check the other certificates of the chain if there are more
290 than one certificate ids in cert_ids. */
291 if (sk_ESS_CERT_ID_num(cert_ids)sk_num(((_STACK*) (1 ? (cert_ids) : (struct stack_st_ESS_CERT_ID
*)0)))
> 1) {
292 /* All the certificates of the chain must be in cert_ids. */
293 for (i = 1; i < sk_X509_num(chain)sk_num(((_STACK*) (1 ? (chain) : (struct stack_st_X509*)0))); ++i) {
294 cert = sk_X509_value(chain, i)((X509 *)sk_value(((_STACK*) (1 ? (chain) : (struct stack_st_X509
*)0)), (i)))
;
295 if (TS_find_cert(cert_ids, cert) < 0)
296 goto err;
297 }
298 }
299 ret = 1;
300
301err:
302 if (!ret)
303 TSerror(TS_R_ESS_SIGNING_CERTIFICATE_ERROR)ERR_put_error(47,(0xfff),(101),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,303)
;
304 ESS_SIGNING_CERT_free(ss);
305 return ret;
306}
307
308static ESS_SIGNING_CERT *
309ESS_get_signing_cert(PKCS7_SIGNER_INFO *si)
310{
311 ASN1_TYPE *attr;
312 const unsigned char *p;
313
314 attr = PKCS7_get_signed_attribute(si,
315 NID_id_smime_aa_signingCertificate223);
316 if (!attr)
317 return NULL((void*)0);
318 if (attr->type != V_ASN1_SEQUENCE16)
319 return NULL((void*)0);
320 p = attr->value.sequence->data;
321 return d2i_ESS_SIGNING_CERT(NULL((void*)0), &p, attr->value.sequence->length);
322}
323
324/* Returns < 0 if certificate is not found, certificate index otherwise. */
325static int
326TS_find_cert(STACK_OF(ESS_CERT_ID)struct stack_st_ESS_CERT_ID *cert_ids, X509 *cert)
327{
328 int i;
329 unsigned char cert_hash[TS_HASH_LEN20];
330
331 if (!cert_ids || !cert)
332 return -1;
333
334 if (!X509_digest(cert, TS_HASH_EVPEVP_sha1(), cert_hash, NULL((void*)0)))
335 return -1;
336
337 /* Recompute SHA1 hash of certificate if necessary (side effect). */
338 X509_check_purpose(cert, -1, 0);
339
340 /* Look for cert in the cert_ids vector. */
341 for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids)sk_num(((_STACK*) (1 ? (cert_ids) : (struct stack_st_ESS_CERT_ID
*)0)))
; ++i) {
342 ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i)((ESS_CERT_ID *)sk_value(((_STACK*) (1 ? (cert_ids) : (struct
stack_st_ESS_CERT_ID*)0)), (i)))
;
343
344 /* Check the SHA-1 hash first. */
345 if (cid->hash->length == TS_HASH_LEN20 && !memcmp(cid->hash->data,
346 cert_hash, TS_HASH_LEN20)) {
347 /* Check the issuer/serial as well if specified. */
348 ESS_ISSUER_SERIAL *is = cid->issuer_serial;
349 if (!is || !TS_issuer_serial_cmp(is, cert->cert_info))
350 return i;
351 }
352 }
353
354 return -1;
355}
356
357static int
358TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509_CINF *cinfo)
359{
360 GENERAL_NAME *issuer;
361
362 if (!is || !cinfo || sk_GENERAL_NAME_num(is->issuer)sk_num(((_STACK*) (1 ? (is->issuer) : (struct stack_st_GENERAL_NAME
*)0)))
!= 1)
363 return -1;
364
365 /* Check the issuer first. It must be a directory name. */
366 issuer = sk_GENERAL_NAME_value(is->issuer, 0)((GENERAL_NAME *)sk_value(((_STACK*) (1 ? (is->issuer) : (
struct stack_st_GENERAL_NAME*)0)), (0)))
;
367 if (issuer->type != GEN_DIRNAME4 ||
368 X509_NAME_cmp(issuer->d.dirn, cinfo->issuer))
369 return -1;
370
371 /* Check the serial number, too. */
372 if (ASN1_INTEGER_cmp(is->serial, cinfo->serialNumber))
373 return -1;
374
375 return 0;
376}
377
378/*
379 * Verifies whether 'response' contains a valid response with regards
380 * to the settings of the context:
381 * - Gives an error message if the TS_TST_INFO is not present.
382 * - Calls _TS_RESP_verify_token to verify the token content.
383 */
384int
385TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response)
386{
387 PKCS7 *token = TS_RESP_get_token(response);
388 TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
389 int ret = 0;
390
391 /* Check if we have a successful TS_TST_INFO object in place. */
392 if (!TS_check_status_info(response))
393 goto err;
394
395 /* Check the contents of the time stamp token. */
396 if (!int_TS_RESP_verify_token(ctx, token, tst_info))
397 goto err;
398
399 ret = 1;
400
401err:
402 return ret;
403}
404
405/*
406 * Tries to extract a TS_TST_INFO structure from the PKCS7 token and
407 * calls the internal int_TS_RESP_verify_token function for verifying it.
408 */
409int
410TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token)
411{
412 TS_TST_INFO *tst_info = PKCS7_to_TS_TST_INFO(token);
413 int ret = 0;
414
415 if (tst_info) {
416 ret = int_TS_RESP_verify_token(ctx, token, tst_info);
417 TS_TST_INFO_free(tst_info);
418 }
419 return ret;
420}
421
422/*
423 * Verifies whether the 'token' contains a valid time stamp token
424 * with regards to the settings of the context. Only those checks are
425 * carried out that are specified in the context:
426 * - Verifies the signature of the TS_TST_INFO.
427 * - Checks the version number of the response.
428 * - Check if the requested and returned policies math.
429 * - Check if the message imprints are the same.
430 * - Check if the nonces are the same.
431 * - Check if the TSA name matches the signer.
432 * - Check if the TSA name is the expected TSA.
433 */
434static int
435int_TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token,
436 TS_TST_INFO *tst_info)
437{
438 X509 *signer = NULL((void*)0);
439 GENERAL_NAME *tsa_name = TS_TST_INFO_get_tsa(tst_info);
440 X509_ALGOR *md_alg = NULL((void*)0);
441 unsigned char *imprint = NULL((void*)0);
442 unsigned imprint_len = 0;
443 int ret = 0;
444
445 /* Verify the signature. */
446 if ((ctx->flags & TS_VFY_SIGNATURE(1u << 0)) &&
447 !TS_RESP_verify_signature(token, ctx->certs, ctx->store, &signer))
448 goto err;
449
450 /* Check version number of response. */
451 if ((ctx->flags & TS_VFY_VERSION(1u << 1)) &&
452 TS_TST_INFO_get_version(tst_info) != 1) {
453 TSerror(TS_R_UNSUPPORTED_VERSION)ERR_put_error(47,(0xfff),(113),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,453)
;
454 goto err;
455 }
456
457 /* Check policies. */
458 if ((ctx->flags & TS_VFY_POLICY(1u << 2)) &&
459 !TS_check_policy(ctx->policy, tst_info))
460 goto err;
461
462 /* Check message imprints. */
463 if ((ctx->flags & TS_VFY_IMPRINT(1u << 3)) &&
464 !TS_check_imprints(ctx->md_alg, ctx->imprint, ctx->imprint_len,
465 tst_info))
466 goto err;
467
468 /* Compute and check message imprints. */
469 if ((ctx->flags & TS_VFY_DATA(1u << 4)) &&
470 (!TS_compute_imprint(ctx->data, tst_info,
471 &md_alg, &imprint, &imprint_len) ||
472 !TS_check_imprints(md_alg, imprint, imprint_len, tst_info)))
473 goto err;
474
475 /* Check nonces. */
476 if ((ctx->flags & TS_VFY_NONCE(1u << 5)) &&
477 !TS_check_nonces(ctx->nonce, tst_info))
478 goto err;
479
480 /* Check whether TSA name and signer certificate match. */
481 if ((ctx->flags & TS_VFY_SIGNER(1u << 6)) &&
482 tsa_name && !TS_check_signer_name(tsa_name, signer)) {
483 TSerror(TS_R_TSA_NAME_MISMATCH)ERR_put_error(47,(0xfff),(111),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,483)
;
484 goto err;
485 }
486
487 /* Check whether the TSA is the expected one. */
488 if ((ctx->flags & TS_VFY_TSA_NAME(1u << 7)) &&
489 !TS_check_signer_name(ctx->tsa_name, signer)) {
490 TSerror(TS_R_TSA_UNTRUSTED)ERR_put_error(47,(0xfff),(112),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,490)
;
491 goto err;
492 }
493
494 ret = 1;
495
496err:
497 X509_free(signer);
498 X509_ALGOR_free(md_alg);
499 free(imprint);
500 return ret;
501}
502
503static int
504TS_check_status_info(TS_RESP *response)
505{
506 TS_STATUS_INFO *info = TS_RESP_get_status_info(response);
507 long status = ASN1_INTEGER_get(info->status);
508 const char *status_text = NULL((void*)0);
509 char *embedded_status_text = NULL((void*)0);
510 char failure_text[TS_STATUS_BUF_SIZE256] = "";
511
512 /* Check if everything went fine. */
513 if (status == 0 || status == 1)
514 return 1;
515
516 /* There was an error, get the description in status_text. */
517 if (0 <= status && status < (long)TS_STATUS_TEXT_SIZE(sizeof(TS_status_text)/sizeof(*TS_status_text)))
518 status_text = TS_status_text[status];
519 else
520 status_text = "unknown code";
521
522 /* Set the embedded_status_text to the returned description. */
523 if (sk_ASN1_UTF8STRING_num(info->text)sk_num(((_STACK*) (1 ? (info->text) : (struct stack_st_ASN1_UTF8STRING
*)0)))
> 0 &&
524 !(embedded_status_text = TS_get_status_text(info->text)))
525 return 0;
526
527 /* Filling in failure_text with the failure information. */
528 if (info->failure_info) {
529 int i;
530 int first = 1;
531 for (i = 0; i < (int)TS_FAILURE_INFO_SIZE(sizeof(TS_failure_info) / sizeof(*TS_failure_info)); ++i) {
532 if (ASN1_BIT_STRING_get_bit(info->failure_info,
533 TS_failure_info[i].code)) {
534 if (!first)
535 strlcat(failure_text, ",",
536 TS_STATUS_BUF_SIZE256);
537 else
538 first = 0;
539 strlcat(failure_text, TS_failure_info[i].text,
540 TS_STATUS_BUF_SIZE256);
541 }
542 }
543 }
544 if (failure_text[0] == '\0')
545 strlcpy(failure_text, "unspecified", TS_STATUS_BUF_SIZE256);
546
547 /* Making up the error string. */
548 TSerror(TS_R_NO_TIME_STAMP_TOKEN)ERR_put_error(47,(0xfff),(107),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,548)
;
549 ERR_asprintf_error_data
550 ("status code: %s, status text: %s, failure codes: %s",
551 status_text,
552 embedded_status_text ? embedded_status_text : "unspecified",
553 failure_text);
554 free(embedded_status_text);
555
556 return 0;
557}
558
559static char *
560TS_get_status_text(STACK_OF(ASN1_UTF8STRING)struct stack_st_ASN1_UTF8STRING *text)
561{
562 int i;
563 unsigned int length = 0;
564 char *result = NULL((void*)0);
565
566 /* Determine length first. */
567 for (i = 0; i < sk_ASN1_UTF8STRING_num(text)sk_num(((_STACK*) (1 ? (text) : (struct stack_st_ASN1_UTF8STRING
*)0)))
; ++i) {
568 ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i)((ASN1_UTF8STRING *)sk_value(((_STACK*) (1 ? (text) : (struct
stack_st_ASN1_UTF8STRING*)0)), (i)))
;
569 length += ASN1_STRING_length(current);
570 length += 1; /* separator character */
571 }
572 /* Allocate memory (closing '\0' included). */
573 if (!(result = malloc(length))) {
574 TSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(47,(0xfff),((1|64)),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,574)
;
575 return NULL((void*)0);
576 }
577 /* Concatenate the descriptions. */
578 result[0] = '\0';
579 for (i = 0; i < sk_ASN1_UTF8STRING_num(text)sk_num(((_STACK*) (1 ? (text) : (struct stack_st_ASN1_UTF8STRING
*)0)))
; ++i) {
580 ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i)((ASN1_UTF8STRING *)sk_value(((_STACK*) (1 ? (text) : (struct
stack_st_ASN1_UTF8STRING*)0)), (i)))
;
581 if (i > 0)
582 strlcat(result, "/", length);
583 strlcat(result, (const char *)ASN1_STRING_data(current), length);
584 }
585 return result;
586}
587
588static int
589TS_check_policy(ASN1_OBJECT *req_oid, TS_TST_INFO *tst_info)
590{
591 ASN1_OBJECT *resp_oid = TS_TST_INFO_get_policy_id(tst_info);
592
593 if (OBJ_cmp(req_oid, resp_oid) != 0) {
594 TSerror(TS_R_POLICY_MISMATCH)ERR_put_error(47,(0xfff),(108),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,594)
;
595 return 0;
596 }
597
598 return 1;
599}
600
601static int
602TS_compute_imprint(BIO *data, TS_TST_INFO *tst_info, X509_ALGOR **out_md_alg,
603 unsigned char **out_imprint, unsigned int *out_imprint_len)
604{
605 TS_MSG_IMPRINT *msg_imprint;
606 X509_ALGOR *md_alg_resp;
607 X509_ALGOR *md_alg = NULL((void*)0);
608 unsigned char *imprint = NULL((void*)0);
609 unsigned int imprint_len = 0;
610 const EVP_MD *md;
611 EVP_MD_CTX md_ctx;
612 unsigned char buffer[4096];
613 int length;
614
615 *out_md_alg = NULL((void*)0);
616 *out_imprint = NULL((void*)0);
617 *out_imprint_len = 0;
618
619 /* Retrieve the MD algorithm of the response. */
620 msg_imprint = TS_TST_INFO_get_msg_imprint(tst_info);
621 md_alg_resp = TS_MSG_IMPRINT_get_algo(msg_imprint);
622 if ((md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL((void*)0))
623 goto err;
624
625 /* Getting the MD object. */
626 if ((md = EVP_get_digestbyobj((md_alg)->algorithm)EVP_get_digestbyname(OBJ_nid2sn(OBJ_obj2nid((md_alg)->algorithm
)))
) == NULL((void*)0)) {
627 TSerror(TS_R_UNSUPPORTED_MD_ALGORITHM)ERR_put_error(47,(0xfff),(126),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,627)
;
628 goto err;
629 }
630
631 /* Compute message digest. */
632 if ((length = EVP_MD_size(md)) < 0)
633 goto err;
634 imprint_len = length;
635 if ((imprint = malloc(imprint_len)) == NULL((void*)0)) {
636 TSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(47,(0xfff),((1|64)),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,636)
;
637 goto err;
638 }
639
640 if (!EVP_DigestInit(&md_ctx, md))
641 goto err;
642 while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) {
643 if (!EVP_DigestUpdate(&md_ctx, buffer, length))
644 goto err;
645 }
646 if (!EVP_DigestFinal(&md_ctx, imprint, NULL((void*)0)))
647 goto err;
648
649 *out_md_alg = md_alg;
650 md_alg = NULL((void*)0);
651 *out_imprint = imprint;
652 imprint = NULL((void*)0);
653 *out_imprint_len = imprint_len;
654
655 return 1;
656
657err:
658 X509_ALGOR_free(md_alg);
659 free(imprint);
660 return 0;
661}
662
663static int
664TS_check_imprints(X509_ALGOR *algor_a, unsigned char *imprint_a, unsigned len_a,
665 TS_TST_INFO *tst_info)
666{
667 TS_MSG_IMPRINT *b = TS_TST_INFO_get_msg_imprint(tst_info);
668 X509_ALGOR *algor_b = TS_MSG_IMPRINT_get_algo(b);
669 int ret = 0;
670
671 /* algor_a is optional. */
672 if (algor_a) {
673 /* Compare algorithm OIDs. */
674 if (OBJ_cmp(algor_a->algorithm, algor_b->algorithm))
675 goto err;
676
677 /* The parameter must be NULL in both. */
678 if ((algor_a->parameter &&
679 ASN1_TYPE_get(algor_a->parameter) != V_ASN1_NULL5) ||
680 (algor_b->parameter &&
681 ASN1_TYPE_get(algor_b->parameter) != V_ASN1_NULL5))
682 goto err;
683 }
684
685 /* Compare octet strings. */
686 ret = len_a == (unsigned) ASN1_STRING_length(b->hashed_msg) &&
687 memcmp(imprint_a, ASN1_STRING_data(b->hashed_msg), len_a) == 0;
688
689err:
690 if (!ret)
691 TSerror(TS_R_MESSAGE_IMPRINT_MISMATCH)ERR_put_error(47,(0xfff),(103),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,691)
;
692 return ret;
693}
694
695static int
696TS_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info)
697{
698 const ASN1_INTEGER *b = TS_TST_INFO_get_nonce(tst_info);
699
700 /* Error if nonce is missing. */
701 if (!b) {
702 TSerror(TS_R_NONCE_NOT_RETURNED)ERR_put_error(47,(0xfff),(105),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,702)
;
703 return 0;
704 }
705
706 /* No error if a nonce is returned without being requested. */
707 if (ASN1_INTEGER_cmp(a, b) != 0) {
708 TSerror(TS_R_NONCE_MISMATCH)ERR_put_error(47,(0xfff),(104),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,708)
;
709 return 0;
710 }
711
712 return 1;
713}
714
715/* Check if the specified TSA name matches either the subject
716 or one of the subject alternative names of the TSA certificate. */
717static int
718TS_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer)
719{
720 STACK_OF(GENERAL_NAME)struct stack_st_GENERAL_NAME *gen_names = NULL((void*)0);
721 int idx = -1;
722 int found = 0;
723
724 if (signer == NULL((void*)0))
725 return 0;
726
727 /* Check the subject name first. */
728 if (tsa_name->type == GEN_DIRNAME4 &&
729 X509_NAME_cmp(tsa_name->d.dirn, signer->cert_info->subject) == 0)
730 return 1;
731
732 /* Check all the alternative names. */
733 gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name85,
734 NULL((void*)0), &idx);
735 while (gen_names != NULL((void*)0) &&
736 !(found = (TS_find_name(gen_names, tsa_name) >= 0))) {
737 /* Get the next subject alternative name,
738 although there should be no more than one. */
739 GENERAL_NAMES_free(gen_names);
740 gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name85,
741 NULL((void*)0), &idx);
742 }
743 if (gen_names)
744 GENERAL_NAMES_free(gen_names);
745
746 return found;
747}
748
749/* Returns 1 if name is in gen_names, 0 otherwise. */
750static int
751TS_find_name(STACK_OF(GENERAL_NAME)struct stack_st_GENERAL_NAME *gen_names, GENERAL_NAME *name)
752{
753 int i, found;
754 for (i = 0, found = 0; !found && i < sk_GENERAL_NAME_num(gen_names)sk_num(((_STACK*) (1 ? (gen_names) : (struct stack_st_GENERAL_NAME
*)0)))
;
755 ++i) {
756 GENERAL_NAME *current = sk_GENERAL_NAME_value(gen_names, i)((GENERAL_NAME *)sk_value(((_STACK*) (1 ? (gen_names) : (struct
stack_st_GENERAL_NAME*)0)), (i)))
;
757 found = GENERAL_NAME_cmp(current, name) == 0;
758 }
759 return found ? i - 1 : -1;
760}