Bug Summary

File:src/lib/libcrypto/ts/ts_rsp_verify.c
Warning:line 208, 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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ts_rsp_verify.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/llvm16/lib/clang/16 -D LIBRESSL_INTERNAL -D HAVE_FUNOPEN -I /usr/src/lib/libcrypto -I /usr/src/lib/libcrypto/arch/amd64 -I /usr/src/lib/libcrypto/asn1 -I /usr/src/lib/libcrypto/bio -I /usr/src/lib/libcrypto/bn -I /usr/src/lib/libcrypto/bn/arch/amd64 -I /usr/src/lib/libcrypto/bytestring -I /usr/src/lib/libcrypto/curve25519 -I /usr/src/lib/libcrypto/dh -I /usr/src/lib/libcrypto/dsa -I /usr/src/lib/libcrypto/ec -I /usr/src/lib/libcrypto/ecdsa -I /usr/src/lib/libcrypto/evp -I /usr/src/lib/libcrypto/hidden -I /usr/src/lib/libcrypto/hmac -I /usr/src/lib/libcrypto/kdf -I /usr/src/lib/libcrypto/modes -I /usr/src/lib/libcrypto/ocsp -I /usr/src/lib/libcrypto/pkcs12 -I /usr/src/lib/libcrypto/rsa -I /usr/src/lib/libcrypto/sha -I /usr/src/lib/libcrypto/ts -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 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/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libcrypto/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/lib/libcrypto/ts/ts_rsp_verify.c
1/* $OpenBSD: ts_rsp_verify.c,v 1.30 2023/07/07 07:25:21 beck 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_local.h"
68#include "ts_local.h"
69#include "x509_local.h"
70
71/* Private function declarations. */
72
73static int TS_verify_cert(X509_STORE *store, STACK_OF(X509)struct stack_st_X509 *untrusted,
74 X509 *signer, STACK_OF(X509)struct stack_st_X509 **chain);
75static int TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509)struct stack_st_X509 *chain);
76static ESS_SIGNING_CERT *ESS_get_signing_cert(PKCS7_SIGNER_INFO *si);
77static int TS_find_cert(STACK_OF(ESS_CERT_ID)struct stack_st_ESS_CERT_ID *cert_ids, X509 *cert);
78static ESS_SIGNING_CERT_V2 *ESS_get_signing_cert_v2(PKCS7_SIGNER_INFO *si);
79static int TS_find_cert_v2(STACK_OF(ESS_CERT_ID_V2)struct stack_st_ESS_CERT_ID_V2 *cert_ids, X509 *cert);
80static int TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert);
81static int int_TS_RESP_verify_token(TS_VERIFY_CTX *ctx,
82 PKCS7 *token, TS_TST_INFO *tst_info);
83static int TS_check_status_info(TS_RESP *response);
84static char *TS_get_status_text(STACK_OF(ASN1_UTF8STRING)struct stack_st_ASN1_UTF8STRING *text);
85static int TS_check_policy(ASN1_OBJECT *req_oid, TS_TST_INFO *tst_info);
86static int TS_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
87 X509_ALGOR **md_alg,
88 unsigned char **imprint, unsigned *imprint_len);
89static int TS_check_imprints(X509_ALGOR *algor_a,
90 unsigned char *imprint_a, unsigned len_a,
91 TS_TST_INFO *tst_info);
92static int TS_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info);
93static int TS_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer);
94static int TS_find_name(STACK_OF(GENERAL_NAME)struct stack_st_GENERAL_NAME *gen_names, GENERAL_NAME *name);
95
96/*
97 * Local mapping between response codes and descriptions.
98 * Don't forget to change TS_STATUS_BUF_SIZE when modifying
99 * the elements of this array.
100 */
101static const char *TS_status_text[] = {
102 "granted",
103 "grantedWithMods",
104 "rejection",
105 "waiting",
106 "revocationWarning",
107 "revocationNotification"
108};
109
110#define TS_STATUS_TEXT_SIZE(sizeof(TS_status_text)/sizeof(*TS_status_text)) (sizeof(TS_status_text)/sizeof(*TS_status_text))
111
112/*
113 * This must be greater or equal to the sum of the strings in TS_status_text
114 * plus the number of its elements.
115 */
116#define TS_STATUS_BUF_SIZE256 256
117
118static struct {
119 int code;
120 const char *text;
121} TS_failure_info[] = {
122 { TS_INFO_BAD_ALG0, "badAlg" },
123 { TS_INFO_BAD_REQUEST2, "badRequest" },
124 { TS_INFO_BAD_DATA_FORMAT5, "badDataFormat" },
125 { TS_INFO_TIME_NOT_AVAILABLE14, "timeNotAvailable" },
126 { TS_INFO_UNACCEPTED_POLICY15, "unacceptedPolicy" },
127 { TS_INFO_UNACCEPTED_EXTENSION16, "unacceptedExtension" },
128 { TS_INFO_ADD_INFO_NOT_AVAILABLE17, "addInfoNotAvailable" },
129 { TS_INFO_SYSTEM_FAILURE25, "systemFailure" }
130};
131
132#define TS_FAILURE_INFO_SIZE(sizeof(TS_failure_info) / sizeof(*TS_failure_info)) (sizeof(TS_failure_info) / \
133 sizeof(*TS_failure_info))
134
135/* Functions for verifying a signed TS_TST_INFO structure. */
136
137/*
138 * This function carries out the following tasks:
139 * - Checks if there is one and only one signer.
140 * - Search for the signing certificate in 'certs' and in the response.
141 * - Check the extended key usage and key usage fields of the signer
142 * certificate (done by the path validation).
143 * - Build and validate the certificate path.
144 * - Check if the certificate path meets the requirements of the
145 * SigningCertificate ESS signed attribute.
146 * - Verify the signature value.
147 * - Returns the signer certificate in 'signer', if 'signer' is not NULL.
148 */
149int
150TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509)struct stack_st_X509 *certs,
151 X509_STORE *store, X509 **signer_out)
152{
153 STACK_OF(PKCS7_SIGNER_INFO)struct stack_st_PKCS7_SIGNER_INFO *sinfos = NULL((void *)0);
154 PKCS7_SIGNER_INFO *si;
155 STACK_OF(X509)struct stack_st_X509 *signers = NULL((void *)0);
156 X509 *signer;
157 STACK_OF(X509)struct stack_st_X509 *chain = NULL((void *)0);
158 char buf[4096];
159 int i, j = 0, ret = 0;
160 BIO *p7bio = NULL((void *)0);
161
162 /* Some sanity checks first. */
163 if (!token) {
164 TSerror(TS_R_INVALID_NULL_POINTER)ERR_put_error(47,(0xfff),(102),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,164)
;
165 goto err;
166 }
167
168 /* Check for the correct content type */
169 if (!PKCS7_type_is_signed(token)(OBJ_obj2nid((token)->type) == 22)) {
170 TSerror(TS_R_WRONG_CONTENT_TYPE)ERR_put_error(47,(0xfff),(114),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,170)
;
171 goto err;
172 }
173
174 /* Check if there is one and only one signer. */
175 sinfos = PKCS7_get_signer_info(token);
176 if (!sinfos || sk_PKCS7_SIGNER_INFO_num(sinfos)sk_num(((_STACK*) (1 ? (sinfos) : (struct stack_st_PKCS7_SIGNER_INFO
*)0)))
!= 1) {
177 TSerror(TS_R_THERE_MUST_BE_ONE_SIGNER)ERR_put_error(47,(0xfff),(110),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,177)
;
178 goto err;
179 }
180 si = sk_PKCS7_SIGNER_INFO_value(sinfos, 0)((PKCS7_SIGNER_INFO *)sk_value(((_STACK*) (1 ? (sinfos) : (struct
stack_st_PKCS7_SIGNER_INFO*)0)), (0)))
;
181
182 /* Check for no content: no data to verify signature. */
183 if (PKCS7_get_detached(token)PKCS7_ctrl(token,2,0,((void *)0))) {
184 TSerror(TS_R_NO_CONTENT)ERR_put_error(47,(0xfff),(106),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,184)
;
185 goto err;
186 }
187
188 /* Get hold of the signer certificate, search only internal
189 certificates if it was requested. */
190 signers = PKCS7_get0_signers(token, certs, 0);
191 if (!signers || sk_X509_num(signers)sk_num(((_STACK*) (1 ? (signers) : (struct stack_st_X509*)0))
)
!= 1)
192 goto err;
193 signer = sk_X509_value(signers, 0)((X509 *)sk_value(((_STACK*) (1 ? (signers) : (struct stack_st_X509
*)0)), (0)))
;
194
195 /* Now verify the certificate. */
196 if (!TS_verify_cert(store, certs, signer, &chain))
197 goto err;
198
199 /* Check if the signer certificate is consistent with the
200 ESS extension. */
201 if (!TS_check_signing_certs(si, chain))
202 goto err;
203
204 /* Creating the message digest. */
205 p7bio = PKCS7_dataInit(token, NULL((void *)0));
206
207 /* We now have to 'read' from p7bio to calculate digests etc. */
208 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'
209 ;
210
211 /* Verifying the signature. */
212 j = PKCS7_signatureVerify(p7bio, token, si, signer);
213 if (j <= 0) {
214 TSerror(TS_R_SIGNATURE_FAILURE)ERR_put_error(47,(0xfff),(109),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,214)
;
215 goto err;
216 }
217
218 /* Return the signer certificate if needed. */
219 if (signer_out) {
220 *signer_out = signer;
221 CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509)CRYPTO_add_lock(&signer->references,1,3,((void *)0),0);
222 }
223
224 ret = 1;
225
226err:
227 BIO_free_all(p7bio);
228 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))))
;
229 sk_X509_free(signers)sk_free(((_STACK*) (1 ? (signers) : (struct stack_st_X509*)0)
))
;
230
231 return ret;
232}
233LCRYPTO_ALIAS(TS_RESP_verify_signature)asm("");
234
235/*
236 * The certificate chain is returned in chain. Caller is responsible for
237 * freeing the vector.
238 */
239static int
240TS_verify_cert(X509_STORE *store, STACK_OF(X509)struct stack_st_X509 *untrusted, X509 *signer,
241 STACK_OF(X509)struct stack_st_X509 **chain)
242{
243 X509_STORE_CTX cert_ctx;
244 int i;
245 int ret = 0;
246
247 /* chain is an out argument. */
248 *chain = NULL((void *)0);
249 if (X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted) == 0) {
250 TSerror(ERR_R_X509_LIB)ERR_put_error(47,(0xfff),(11),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,250)
;
251 goto err;
252 }
253 if (X509_STORE_CTX_set_purpose(&cert_ctx,
254 X509_PURPOSE_TIMESTAMP_SIGN9) == 0)
255 goto err;
256 i = X509_verify_cert(&cert_ctx);
257 if (i <= 0) {
258 int j = X509_STORE_CTX_get_error(&cert_ctx);
259
260 TSerror(TS_R_CERTIFICATE_VERIFY_ERROR)ERR_put_error(47,(0xfff),(100),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,260)
;
261 ERR_asprintf_error_data("Verify error:%s",
262 X509_verify_cert_error_string(j));
263 goto err;
264 } else {
265 /* Get a copy of the certificate chain. */
266 *chain = X509_STORE_CTX_get1_chain(&cert_ctx);
267 ret = 1;
268 }
269
270err:
271 X509_STORE_CTX_cleanup(&cert_ctx);
272
273 return ret;
274}
275
276static int
277TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509)struct stack_st_X509 *chain)
278{
279 ESS_SIGNING_CERT *ss = NULL((void *)0);
280 STACK_OF(ESS_CERT_ID)struct stack_st_ESS_CERT_ID *cert_ids;
281 ESS_SIGNING_CERT_V2 *ssv2 = NULL((void *)0);
282 STACK_OF(ESS_CERT_ID_V2)struct stack_st_ESS_CERT_ID_V2 *cert_ids_v2;
283 X509 *cert;
284 int i = 0;
285 int ret = 0;
286
287 if ((ss = ESS_get_signing_cert(si)) != NULL((void *)0)) {
288 cert_ids = ss->cert_ids;
289 /* The signer certificate must be the first in cert_ids. */
290 cert = sk_X509_value(chain, 0)((X509 *)sk_value(((_STACK*) (1 ? (chain) : (struct stack_st_X509
*)0)), (0)))
;
291
292 if (TS_find_cert(cert_ids, cert) != 0)
293 goto err;
294
295 /*
296 * Check the other certificates of the chain if there are more
297 * than one certificate ids in cert_ids.
298 */
299 if (sk_ESS_CERT_ID_num(cert_ids)sk_num(((_STACK*) (1 ? (cert_ids) : (struct stack_st_ESS_CERT_ID
*)0)))
> 1) {
300 /* All the certificates of the chain must be in cert_ids. */
301 for (i = 1; i < sk_X509_num(chain)sk_num(((_STACK*) (1 ? (chain) : (struct stack_st_X509*)0))); i++) {
302 cert = sk_X509_value(chain, i)((X509 *)sk_value(((_STACK*) (1 ? (chain) : (struct stack_st_X509
*)0)), (i)))
;
303
304 if (TS_find_cert(cert_ids, cert) < 0)
305 goto err;
306 }
307 }
308 }
309
310 if ((ssv2 = ESS_get_signing_cert_v2(si)) != NULL((void *)0)) {
311 cert_ids_v2 = ssv2->cert_ids;
312 /* The signer certificate must be the first in cert_ids_v2. */
313 cert = sk_X509_value(chain, 0)((X509 *)sk_value(((_STACK*) (1 ? (chain) : (struct stack_st_X509
*)0)), (0)))
;
314
315 if (TS_find_cert_v2(cert_ids_v2, cert) != 0)
316 goto err;
317
318 /*
319 * Check the other certificates of the chain if there are more
320 * than one certificate ids in cert_ids_v2.
321 */
322 if (sk_ESS_CERT_ID_V2_num(cert_ids_v2)sk_num(((_STACK*) (1 ? (cert_ids_v2) : (struct stack_st_ESS_CERT_ID_V2
*)0)))
> 1) {
323 /* All the certificates of the chain must be in cert_ids_v2. */
324 for (i = 1; i < sk_X509_num(chain)sk_num(((_STACK*) (1 ? (chain) : (struct stack_st_X509*)0))); i++) {
325 cert = sk_X509_value(chain, i)((X509 *)sk_value(((_STACK*) (1 ? (chain) : (struct stack_st_X509
*)0)), (i)))
;
326
327 if (TS_find_cert_v2(cert_ids_v2, cert) < 0)
328 goto err;
329 }
330 }
331 }
332
333 ret = 1;
334
335err:
336 if (!ret)
337 TSerror(TS_R_ESS_SIGNING_CERTIFICATE_ERROR)ERR_put_error(47,(0xfff),(101),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,337)
;
338 ESS_SIGNING_CERT_free(ss);
339 ESS_SIGNING_CERT_V2_free(ssv2);
340 return ret;
341}
342
343static ESS_SIGNING_CERT *
344ESS_get_signing_cert(PKCS7_SIGNER_INFO *si)
345{
346 ASN1_TYPE *attr;
347 const unsigned char *p;
348
349 attr = PKCS7_get_signed_attribute(si,
350 NID_id_smime_aa_signingCertificate223);
351 if (!attr)
352 return NULL((void *)0);
353 if (attr->type != V_ASN1_SEQUENCE16)
354 return NULL((void *)0);
355 p = attr->value.sequence->data;
356 return d2i_ESS_SIGNING_CERT(NULL((void *)0), &p, attr->value.sequence->length);
357}
358
359static ESS_SIGNING_CERT_V2 *
360ESS_get_signing_cert_v2(PKCS7_SIGNER_INFO *si)
361{
362 ASN1_TYPE *attr;
363 const unsigned char *p;
364
365 attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV21023);
366 if (attr == NULL((void *)0))
367 return NULL((void *)0);
368 p = attr->value.sequence->data;
369 return d2i_ESS_SIGNING_CERT_V2(NULL((void *)0), &p, attr->value.sequence->length);
370}
371
372/* Returns < 0 if certificate is not found, certificate index otherwise. */
373static int
374TS_find_cert(STACK_OF(ESS_CERT_ID)struct stack_st_ESS_CERT_ID *cert_ids, X509 *cert)
375{
376 int i;
377 unsigned char cert_hash[TS_HASH_LEN20];
378
379 if (!cert_ids || !cert)
380 return -1;
381
382 if (!X509_digest(cert, TS_HASH_EVPEVP_sha1(), cert_hash, NULL((void *)0)))
383 return -1;
384
385 /* Recompute SHA1 hash of certificate if necessary (side effect). */
386 if (X509_check_purpose(cert, -1, 0) == -1)
387 return -1;
388
389 /* Look for cert in the cert_ids vector. */
390 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) {
391 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)))
;
392
393 /* Check the SHA-1 hash first. */
394 if (cid->hash->length == TS_HASH_LEN20 && !memcmp(cid->hash->data,
395 cert_hash, TS_HASH_LEN20)) {
396 /* Check the issuer/serial as well if specified. */
397 ESS_ISSUER_SERIAL *is = cid->issuer_serial;
398
399 if (is == NULL((void *)0) || TS_issuer_serial_cmp(is, cert) == 0)
400 return i;
401 }
402 }
403
404 return -1;
405}
406
407/* Returns < 0 if certificate is not found, certificate index otherwise. */
408static int
409TS_find_cert_v2(STACK_OF(ESS_CERT_ID_V2)struct stack_st_ESS_CERT_ID_V2 *cert_ids, X509 *cert)
410{
411 int i;
412 unsigned char cert_digest[EVP_MAX_MD_SIZE64];
413 unsigned int len;
414
415 /* Look for cert in the cert_ids vector. */
416 for (i = 0; i < sk_ESS_CERT_ID_V2_num(cert_ids)sk_num(((_STACK*) (1 ? (cert_ids) : (struct stack_st_ESS_CERT_ID_V2
*)0)))
; ++i) {
417 ESS_CERT_ID_V2 *cid = sk_ESS_CERT_ID_V2_value(cert_ids, i)((ESS_CERT_ID_V2 *)sk_value(((_STACK*) (1 ? (cert_ids) : (struct
stack_st_ESS_CERT_ID_V2*)0)), (i)))
;
418 const EVP_MD *md = EVP_sha256();
419
420 if (cid->hash_alg != NULL((void *)0))
421 md = EVP_get_digestbyobj(cid->hash_alg->algorithm)EVP_get_digestbyname(OBJ_nid2sn(OBJ_obj2nid(cid->hash_alg->
algorithm)))
;
422 if (md == NULL((void *)0))
423 return -1;
424
425 if (!X509_digest(cert, md, cert_digest, &len))
426 return -1;
427
428 if ((unsigned int)cid->hash->length != len)
429 return -1;
430
431 if (memcmp(cid->hash->data, cert_digest, cid->hash->length) == 0) {
432 ESS_ISSUER_SERIAL *is = cid->issuer_serial;
433
434 if (is == NULL((void *)0) || TS_issuer_serial_cmp(is, cert) == 0)
435 return i;
436 }
437 }
438
439 return -1;
440}
441
442static int
443TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert)
444{
445 GENERAL_NAME *issuer;
446
447 if (is == NULL((void *)0) || cert == NULL((void *)0) || sk_GENERAL_NAME_num(is->issuer)sk_num(((_STACK*) (1 ? (is->issuer) : (struct stack_st_GENERAL_NAME
*)0)))
!= 1)
448 return -1;
449
450 /* Check the issuer first. It must be a directory name. */
451 issuer = sk_GENERAL_NAME_value(is->issuer, 0)((GENERAL_NAME *)sk_value(((_STACK*) (1 ? (is->issuer) : (
struct stack_st_GENERAL_NAME*)0)), (0)))
;
452 if (issuer->type != GEN_DIRNAME4 ||
453 X509_NAME_cmp(issuer->d.dirn, X509_get_issuer_name(cert)))
454 return -1;
455
456 /* Check the serial number, too. */
457 if (ASN1_INTEGER_cmp(is->serial, X509_get_serialNumber(cert)))
458 return -1;
459
460 return 0;
461}
462
463/*
464 * Verifies whether 'response' contains a valid response with regards
465 * to the settings of the context:
466 * - Gives an error message if the TS_TST_INFO is not present.
467 * - Calls _TS_RESP_verify_token to verify the token content.
468 */
469int
470TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response)
471{
472 PKCS7 *token = TS_RESP_get_token(response);
473 TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
474 int ret = 0;
475
476 /* Check if we have a successful TS_TST_INFO object in place. */
477 if (!TS_check_status_info(response))
478 goto err;
479
480 /* Check the contents of the time stamp token. */
481 if (!int_TS_RESP_verify_token(ctx, token, tst_info))
482 goto err;
483
484 ret = 1;
485
486err:
487 return ret;
488}
489LCRYPTO_ALIAS(TS_RESP_verify_response)asm("");
490
491/*
492 * Tries to extract a TS_TST_INFO structure from the PKCS7 token and
493 * calls the internal int_TS_RESP_verify_token function for verifying it.
494 */
495int
496TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token)
497{
498 TS_TST_INFO *tst_info = PKCS7_to_TS_TST_INFO(token);
499 int ret = 0;
500
501 if (tst_info) {
502 ret = int_TS_RESP_verify_token(ctx, token, tst_info);
503 TS_TST_INFO_free(tst_info);
504 }
505 return ret;
506}
507LCRYPTO_ALIAS(TS_RESP_verify_token)asm("");
508
509/*
510 * Verifies whether the 'token' contains a valid time stamp token
511 * with regards to the settings of the context. Only those checks are
512 * carried out that are specified in the context:
513 * - Verifies the signature of the TS_TST_INFO.
514 * - Checks the version number of the response.
515 * - Check if the requested and returned policies math.
516 * - Check if the message imprints are the same.
517 * - Check if the nonces are the same.
518 * - Check if the TSA name matches the signer.
519 * - Check if the TSA name is the expected TSA.
520 */
521static int
522int_TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token,
523 TS_TST_INFO *tst_info)
524{
525 X509 *signer = NULL((void *)0);
526 GENERAL_NAME *tsa_name = TS_TST_INFO_get_tsa(tst_info);
527 X509_ALGOR *md_alg = NULL((void *)0);
528 unsigned char *imprint = NULL((void *)0);
529 unsigned imprint_len = 0;
530 int ret = 0;
531
532 /* Verify the signature. */
533 if ((ctx->flags & TS_VFY_SIGNATURE(1u << 0)) &&
534 !TS_RESP_verify_signature(token, ctx->certs, ctx->store, &signer))
535 goto err;
536
537 /* Check version number of response. */
538 if ((ctx->flags & TS_VFY_VERSION(1u << 1)) &&
539 TS_TST_INFO_get_version(tst_info) != 1) {
540 TSerror(TS_R_UNSUPPORTED_VERSION)ERR_put_error(47,(0xfff),(113),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,540)
;
541 goto err;
542 }
543
544 /* Check policies. */
545 if ((ctx->flags & TS_VFY_POLICY(1u << 2)) &&
546 !TS_check_policy(ctx->policy, tst_info))
547 goto err;
548
549 /* Check message imprints. */
550 if ((ctx->flags & TS_VFY_IMPRINT(1u << 3)) &&
551 !TS_check_imprints(ctx->md_alg, ctx->imprint, ctx->imprint_len,
552 tst_info))
553 goto err;
554
555 /* Compute and check message imprints. */
556 if ((ctx->flags & TS_VFY_DATA(1u << 4)) &&
557 (!TS_compute_imprint(ctx->data, tst_info,
558 &md_alg, &imprint, &imprint_len) ||
559 !TS_check_imprints(md_alg, imprint, imprint_len, tst_info)))
560 goto err;
561
562 /* Check nonces. */
563 if ((ctx->flags & TS_VFY_NONCE(1u << 5)) &&
564 !TS_check_nonces(ctx->nonce, tst_info))
565 goto err;
566
567 /* Check whether TSA name and signer certificate match. */
568 if ((ctx->flags & TS_VFY_SIGNER(1u << 6)) &&
569 tsa_name && !TS_check_signer_name(tsa_name, signer)) {
570 TSerror(TS_R_TSA_NAME_MISMATCH)ERR_put_error(47,(0xfff),(111),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,570)
;
571 goto err;
572 }
573
574 /* Check whether the TSA is the expected one. */
575 if ((ctx->flags & TS_VFY_TSA_NAME(1u << 7)) &&
576 !TS_check_signer_name(ctx->tsa_name, signer)) {
577 TSerror(TS_R_TSA_UNTRUSTED)ERR_put_error(47,(0xfff),(112),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,577)
;
578 goto err;
579 }
580
581 ret = 1;
582
583err:
584 X509_free(signer);
585 X509_ALGOR_free(md_alg);
586 free(imprint);
587 return ret;
588}
589
590static int
591TS_check_status_info(TS_RESP *response)
592{
593 TS_STATUS_INFO *info = TS_RESP_get_status_info(response);
594 long status = ASN1_INTEGER_get(info->status);
595 const char *status_text = NULL((void *)0);
596 char *embedded_status_text = NULL((void *)0);
597 char failure_text[TS_STATUS_BUF_SIZE256] = "";
598
599 /* Check if everything went fine. */
600 if (status == 0 || status == 1)
601 return 1;
602
603 /* There was an error, get the description in status_text. */
604 if (0 <= status && status < (long)TS_STATUS_TEXT_SIZE(sizeof(TS_status_text)/sizeof(*TS_status_text)))
605 status_text = TS_status_text[status];
606 else
607 status_text = "unknown code";
608
609 /* Set the embedded_status_text to the returned description. */
610 if (sk_ASN1_UTF8STRING_num(info->text)sk_num(((_STACK*) (1 ? (info->text) : (struct stack_st_ASN1_UTF8STRING
*)0)))
> 0 &&
611 !(embedded_status_text = TS_get_status_text(info->text)))
612 return 0;
613
614 /* Filling in failure_text with the failure information. */
615 if (info->failure_info) {
616 int i;
617 int first = 1;
618 for (i = 0; i < (int)TS_FAILURE_INFO_SIZE(sizeof(TS_failure_info) / sizeof(*TS_failure_info)); ++i) {
619 if (ASN1_BIT_STRING_get_bit(info->failure_info,
620 TS_failure_info[i].code)) {
621 if (!first)
622 strlcat(failure_text, ",",
623 TS_STATUS_BUF_SIZE256);
624 else
625 first = 0;
626 strlcat(failure_text, TS_failure_info[i].text,
627 TS_STATUS_BUF_SIZE256);
628 }
629 }
630 }
631 if (failure_text[0] == '\0')
632 strlcpy(failure_text, "unspecified", TS_STATUS_BUF_SIZE256);
633
634 /* Making up the error string. */
635 TSerror(TS_R_NO_TIME_STAMP_TOKEN)ERR_put_error(47,(0xfff),(107),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,635)
;
636 ERR_asprintf_error_data
637 ("status code: %s, status text: %s, failure codes: %s",
638 status_text,
639 embedded_status_text ? embedded_status_text : "unspecified",
640 failure_text);
641 free(embedded_status_text);
642
643 return 0;
644}
645
646static char *
647TS_get_status_text(STACK_OF(ASN1_UTF8STRING)struct stack_st_ASN1_UTF8STRING *text)
648{
649 int i;
650 unsigned int length = 0;
651 char *result = NULL((void *)0);
652
653 /* Determine length first. */
654 for (i = 0; i < sk_ASN1_UTF8STRING_num(text)sk_num(((_STACK*) (1 ? (text) : (struct stack_st_ASN1_UTF8STRING
*)0)))
; ++i) {
655 ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i)((ASN1_UTF8STRING *)sk_value(((_STACK*) (1 ? (text) : (struct
stack_st_ASN1_UTF8STRING*)0)), (i)))
;
656 length += ASN1_STRING_length(current);
657 length += 1; /* separator character */
658 }
659 /* Allocate memory (closing '\0' included). */
660 if (!(result = malloc(length))) {
661 TSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(47,(0xfff),((1|64)),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,661)
;
662 return NULL((void *)0);
663 }
664 /* Concatenate the descriptions. */
665 result[0] = '\0';
666 for (i = 0; i < sk_ASN1_UTF8STRING_num(text)sk_num(((_STACK*) (1 ? (text) : (struct stack_st_ASN1_UTF8STRING
*)0)))
; ++i) {
667 ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i)((ASN1_UTF8STRING *)sk_value(((_STACK*) (1 ? (text) : (struct
stack_st_ASN1_UTF8STRING*)0)), (i)))
;
668 if (i > 0)
669 strlcat(result, "/", length);
670 strlcat(result, (const char *)ASN1_STRING_data(current), length);
671 }
672 return result;
673}
674
675static int
676TS_check_policy(ASN1_OBJECT *req_oid, TS_TST_INFO *tst_info)
677{
678 ASN1_OBJECT *resp_oid = TS_TST_INFO_get_policy_id(tst_info);
679
680 if (OBJ_cmp(req_oid, resp_oid) != 0) {
681 TSerror(TS_R_POLICY_MISMATCH)ERR_put_error(47,(0xfff),(108),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,681)
;
682 return 0;
683 }
684
685 return 1;
686}
687
688static int
689TS_compute_imprint(BIO *data, TS_TST_INFO *tst_info, X509_ALGOR **out_md_alg,
690 unsigned char **out_imprint, unsigned int *out_imprint_len)
691{
692 TS_MSG_IMPRINT *msg_imprint;
693 X509_ALGOR *md_alg_resp;
694 X509_ALGOR *md_alg = NULL((void *)0);
695 unsigned char *imprint = NULL((void *)0);
696 unsigned int imprint_len = 0;
697 const EVP_MD *md;
698 EVP_MD_CTX md_ctx;
699 unsigned char buffer[4096];
700 int length;
701
702 *out_md_alg = NULL((void *)0);
703 *out_imprint = NULL((void *)0);
704 *out_imprint_len = 0;
705
706 /* Retrieve the MD algorithm of the response. */
707 msg_imprint = TS_TST_INFO_get_msg_imprint(tst_info);
708 md_alg_resp = TS_MSG_IMPRINT_get_algo(msg_imprint);
709 if ((md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL((void *)0))
710 goto err;
711
712 /* Getting the MD object. */
713 if ((md = EVP_get_digestbyobj((md_alg)->algorithm)EVP_get_digestbyname(OBJ_nid2sn(OBJ_obj2nid((md_alg)->algorithm
)))
) == NULL((void *)0)) {
714 TSerror(TS_R_UNSUPPORTED_MD_ALGORITHM)ERR_put_error(47,(0xfff),(126),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,714)
;
715 goto err;
716 }
717
718 /* Compute message digest. */
719 if ((length = EVP_MD_size(md)) < 0)
720 goto err;
721 imprint_len = length;
722 if ((imprint = malloc(imprint_len)) == NULL((void *)0)) {
723 TSerror(ERR_R_MALLOC_FAILURE)ERR_put_error(47,(0xfff),((1|64)),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,723)
;
724 goto err;
725 }
726
727 if (!EVP_DigestInit(&md_ctx, md))
728 goto err;
729 while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) {
730 if (!EVP_DigestUpdate(&md_ctx, buffer, length))
731 goto err;
732 }
733 if (!EVP_DigestFinal(&md_ctx, imprint, NULL((void *)0)))
734 goto err;
735
736 *out_md_alg = md_alg;
737 md_alg = NULL((void *)0);
738 *out_imprint = imprint;
739 imprint = NULL((void *)0);
740 *out_imprint_len = imprint_len;
741
742 return 1;
743
744err:
745 X509_ALGOR_free(md_alg);
746 free(imprint);
747 return 0;
748}
749
750static int
751TS_check_imprints(X509_ALGOR *algor_a, unsigned char *imprint_a, unsigned len_a,
752 TS_TST_INFO *tst_info)
753{
754 TS_MSG_IMPRINT *b = TS_TST_INFO_get_msg_imprint(tst_info);
755 X509_ALGOR *algor_b = TS_MSG_IMPRINT_get_algo(b);
756 int ret = 0;
757
758 /* algor_a is optional. */
759 if (algor_a) {
760 /* Compare algorithm OIDs. */
761 if (OBJ_cmp(algor_a->algorithm, algor_b->algorithm))
762 goto err;
763
764 /* The parameter must be NULL in both. */
765 if ((algor_a->parameter &&
766 ASN1_TYPE_get(algor_a->parameter) != V_ASN1_NULL5) ||
767 (algor_b->parameter &&
768 ASN1_TYPE_get(algor_b->parameter) != V_ASN1_NULL5))
769 goto err;
770 }
771
772 /* Compare octet strings. */
773 ret = len_a == (unsigned) ASN1_STRING_length(b->hashed_msg) &&
774 memcmp(imprint_a, ASN1_STRING_data(b->hashed_msg), len_a) == 0;
775
776err:
777 if (!ret)
778 TSerror(TS_R_MESSAGE_IMPRINT_MISMATCH)ERR_put_error(47,(0xfff),(103),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,778)
;
779 return ret;
780}
781
782static int
783TS_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info)
784{
785 const ASN1_INTEGER *b = TS_TST_INFO_get_nonce(tst_info);
786
787 /* Error if nonce is missing. */
788 if (!b) {
789 TSerror(TS_R_NONCE_NOT_RETURNED)ERR_put_error(47,(0xfff),(105),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,789)
;
790 return 0;
791 }
792
793 /* No error if a nonce is returned without being requested. */
794 if (ASN1_INTEGER_cmp(a, b) != 0) {
795 TSerror(TS_R_NONCE_MISMATCH)ERR_put_error(47,(0xfff),(104),"/usr/src/lib/libcrypto/ts/ts_rsp_verify.c"
,795)
;
796 return 0;
797 }
798
799 return 1;
800}
801
802/* Check if the specified TSA name matches either the subject
803 or one of the subject alternative names of the TSA certificate. */
804static int
805TS_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer)
806{
807 STACK_OF(GENERAL_NAME)struct stack_st_GENERAL_NAME *gen_names = NULL((void *)0);
808 int idx = -1;
809 int found = 0;
810
811 if (signer == NULL((void *)0))
812 return 0;
813
814 /* Check the subject name first. */
815 if (tsa_name->type == GEN_DIRNAME4 &&
816 X509_name_cmp(tsa_name->d.dirn, X509_get_subject_name(signer))X509_NAME_cmp((tsa_name->d.dirn),(X509_get_subject_name(signer
)))
== 0)
817 return 1;
818
819 /* Check all the alternative names. */
820 gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name85,
821 NULL((void *)0), &idx);
822 while (gen_names != NULL((void *)0) &&
823 !(found = (TS_find_name(gen_names, tsa_name) >= 0))) {
824 /* Get the next subject alternative name,
825 although there should be no more than one. */
826 GENERAL_NAMES_free(gen_names);
827 gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name85,
828 NULL((void *)0), &idx);
829 }
830 if (gen_names)
831 GENERAL_NAMES_free(gen_names);
832
833 return found;
834}
835
836/* Returns 1 if name is in gen_names, 0 otherwise. */
837static int
838TS_find_name(STACK_OF(GENERAL_NAME)struct stack_st_GENERAL_NAME *gen_names, GENERAL_NAME *name)
839{
840 int i, found;
841 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)))
;
842 ++i) {
843 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)))
;
844 found = GENERAL_NAME_cmp(current, name) == 0;
845 }
846 return found ? i - 1 : -1;
847}