LCOV - code coverage report
Current view: top level - ts - ts_rsp_verify.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 170 250 68.0 %
Date: 2014-08-02 Functions: 15 17 88.2 %
Branches: 89 188 47.3 %

           Branch data     Line data    Source code
       1                 :            : /* crypto/ts/ts_resp_verify.c */
       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 "cryptlib.h"
      61                 :            : #include <openssl/objects.h>
      62                 :            : #include <openssl/ts.h>
      63                 :            : #include <openssl/pkcs7.h>
      64                 :            : 
      65                 :            : /* Private function declarations. */
      66                 :            : 
      67                 :            : static int TS_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
      68                 :            :                           X509 *signer, STACK_OF(X509) **chain);
      69                 :            : static int TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509) *chain);
      70                 :            : static ESS_SIGNING_CERT *ESS_get_signing_cert(PKCS7_SIGNER_INFO *si);
      71                 :            : static int TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert);
      72                 :            : static int TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509_CINF *cinfo);
      73                 :            : static int int_TS_RESP_verify_token(TS_VERIFY_CTX *ctx, 
      74                 :            :                                  PKCS7 *token, TS_TST_INFO *tst_info);
      75                 :            : static int TS_check_status_info(TS_RESP *response);
      76                 :            : static char *TS_get_status_text(STACK_OF(ASN1_UTF8STRING) *text);
      77                 :            : static int TS_check_policy(ASN1_OBJECT *req_oid, TS_TST_INFO *tst_info);
      78                 :            : static int TS_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
      79                 :            :                               X509_ALGOR **md_alg, 
      80                 :            :                               unsigned char **imprint, unsigned *imprint_len);
      81                 :            : static int TS_check_imprints(X509_ALGOR *algor_a, 
      82                 :            :                              unsigned char *imprint_a, unsigned len_a,
      83                 :            :                              TS_TST_INFO *tst_info);
      84                 :            : static int TS_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info);
      85                 :            : static int TS_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer);
      86                 :            : static int TS_find_name(STACK_OF(GENERAL_NAME) *gen_names, GENERAL_NAME *name);
      87                 :            : 
      88                 :            : /*
      89                 :            :  * Local mapping between response codes and descriptions.
      90                 :            :  * Don't forget to change TS_STATUS_BUF_SIZE when modifying 
      91                 :            :  * the elements of this array.
      92                 :            :  */
      93                 :            : static const char *TS_status_text[] =
      94                 :            :         { "granted",
      95                 :            :           "grantedWithMods",
      96                 :            :           "rejection",
      97                 :            :           "waiting",
      98                 :            :           "revocationWarning",
      99                 :            :           "revocationNotification" };
     100                 :            : 
     101                 :            : #define TS_STATUS_TEXT_SIZE     (sizeof(TS_status_text)/sizeof(*TS_status_text))
     102                 :            : 
     103                 :            : /*
     104                 :            :  * This must be greater or equal to the sum of the strings in TS_status_text
     105                 :            :  * plus the number of its elements.
     106                 :            :  */
     107                 :            : #define TS_STATUS_BUF_SIZE      256
     108                 :            : 
     109                 :            : static struct
     110                 :            :         {
     111                 :            :         int code;
     112                 :            :         const char *text;
     113                 :            :         } TS_failure_info[] =
     114                 :            :                 { { TS_INFO_BAD_ALG, "badAlg" },
     115                 :            :                   { TS_INFO_BAD_REQUEST, "badRequest" },
     116                 :            :                   { TS_INFO_BAD_DATA_FORMAT, "badDataFormat" },
     117                 :            :                   { TS_INFO_TIME_NOT_AVAILABLE, "timeNotAvailable" },
     118                 :            :                   { TS_INFO_UNACCEPTED_POLICY, "unacceptedPolicy" },
     119                 :            :                   { TS_INFO_UNACCEPTED_EXTENSION, "unacceptedExtension" },
     120                 :            :                   { TS_INFO_ADD_INFO_NOT_AVAILABLE, "addInfoNotAvailable" },
     121                 :            :                   { TS_INFO_SYSTEM_FAILURE, "systemFailure" } };
     122                 :            : 
     123                 :            : #define TS_FAILURE_INFO_SIZE    (sizeof(TS_failure_info) / \
     124                 :            :                                 sizeof(*TS_failure_info))
     125                 :            : 
     126                 :            : /* Functions for verifying a signed TS_TST_INFO structure. */
     127                 :            : 
     128                 :            : /*
     129                 :            :  * This function carries out the following tasks:
     130                 :            :  *      - Checks if there is one and only one signer.
     131                 :            :  *      - Search for the signing certificate in 'certs' and in the response.
     132                 :            :  *      - Check the extended key usage and key usage fields of the signer
     133                 :            :  *      certificate (done by the path validation).
     134                 :            :  *      - Build and validate the certificate path.
     135                 :            :  *      - Check if the certificate path meets the requirements of the
     136                 :            :  *      SigningCertificate ESS signed attribute.
     137                 :            :  *      - Verify the signature value.
     138                 :            :  *      - Returns the signer certificate in 'signer', if 'signer' is not NULL.
     139                 :            :  */
     140                 :          9 : int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
     141                 :            :                              X509_STORE *store, X509 **signer_out)
     142                 :            :         {
     143                 :          9 :         STACK_OF(PKCS7_SIGNER_INFO) *sinfos = NULL;
     144                 :            :         PKCS7_SIGNER_INFO *si;
     145                 :          9 :         STACK_OF(X509) *signers = NULL;
     146                 :            :         X509    *signer;
     147                 :          9 :         STACK_OF(X509) *chain = NULL;
     148                 :            :         char    buf[4096];
     149                 :          9 :         int     i, j = 0, ret = 0;
     150                 :          9 :         BIO     *p7bio = NULL;
     151                 :            : 
     152                 :            :         /* Some sanity checks first. */
     153         [ -  + ]:          9 :         if (!token)
     154                 :            :                 {
     155                 :          0 :                 TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_INVALID_NULL_POINTER);
     156                 :          0 :                 goto err;
     157                 :            :                 }
     158                 :            : 
     159                 :            :         /* Check for the correct content type */
     160         [ -  + ]:          9 :         if(!PKCS7_type_is_signed(token))
     161                 :            :                 {
     162                 :          0 :                 TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_WRONG_CONTENT_TYPE);
     163                 :          0 :                 goto err;
     164                 :            :                 }
     165                 :            : 
     166                 :            :         /* Check if there is one and only one signer. */
     167                 :          9 :         sinfos = PKCS7_get_signer_info(token);
     168 [ +  - ][ -  + ]:          9 :         if (!sinfos || sk_PKCS7_SIGNER_INFO_num(sinfos) != 1)
     169                 :            :                 {
     170                 :          0 :                 TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE,
     171                 :            :                       TS_R_THERE_MUST_BE_ONE_SIGNER);
     172                 :          0 :                 goto err;
     173                 :            :                 }
     174                 :          9 :         si = sk_PKCS7_SIGNER_INFO_value(sinfos, 0);
     175                 :            : 
     176                 :            :         /* Check for no content: no data to verify signature. */
     177         [ -  + ]:          9 :         if (PKCS7_get_detached(token))
     178                 :            :                 {
     179                 :          0 :                 TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_NO_CONTENT);
     180                 :          0 :                 goto err;
     181                 :            :                 }
     182                 :            :         
     183                 :            :         /* Get hold of the signer certificate, search only internal
     184                 :            :            certificates if it was requested. */
     185                 :          9 :         signers = PKCS7_get0_signers(token, certs, 0);
     186 [ +  - ][ +  - ]:          9 :         if (!signers || sk_X509_num(signers) != 1) goto err;
     187                 :          9 :         signer = sk_X509_value(signers, 0);
     188                 :            : 
     189                 :            :         /* Now verify the certificate. */
     190         [ +  - ]:          9 :         if (!TS_verify_cert(store, certs, signer, &chain)) goto err;
     191                 :            : 
     192                 :            :         /* Check if the signer certificate is consistent with the
     193                 :            :            ESS extension. */
     194         [ +  - ]:          9 :         if (!TS_check_signing_certs(si, chain)) goto err;
     195                 :            : 
     196                 :            :         /* Creating the message digest. */
     197                 :          9 :         p7bio = PKCS7_dataInit(token, NULL);
     198                 :            : 
     199                 :            :         /* We now have to 'read' from p7bio to calculate digests etc. */
     200         [ +  + ]:         18 :         while ((i = BIO_read(p7bio,buf,sizeof(buf))) > 0);
     201                 :            : 
     202                 :            :         /* Verifying the signature. */
     203                 :          9 :         j = PKCS7_signatureVerify(p7bio, token, si, signer);
     204         [ -  + ]:          9 :         if (j <= 0)
     205                 :            :                 {
     206                 :          0 :                 TSerr(TS_F_TS_RESP_VERIFY_SIGNATURE, TS_R_SIGNATURE_FAILURE);
     207                 :          0 :                 goto err;
     208                 :            :                 }
     209                 :            : 
     210                 :            :         /* Return the signer certificate if needed. */
     211         [ +  - ]:          9 :         if (signer_out)
     212                 :            :                 {
     213                 :          9 :                 *signer_out = signer;
     214                 :          9 :                 CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
     215                 :            :                 }
     216                 :            : 
     217                 :            :         ret = 1;
     218                 :            : 
     219                 :            :  err:
     220                 :          9 :         BIO_free_all(p7bio);
     221                 :          9 :         sk_X509_pop_free(chain, X509_free);
     222                 :          9 :         sk_X509_free(signers);
     223                 :            : 
     224                 :          9 :         return ret;
     225                 :            :         }
     226                 :            : 
     227                 :            : /*
     228                 :            :  * The certificate chain is returned in chain. Caller is responsible for
     229                 :            :  * freeing the vector.
     230                 :            :  */
     231                 :          9 : static int TS_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
     232                 :            :                           X509 *signer, STACK_OF(X509) **chain)
     233                 :            :         {
     234                 :            :         X509_STORE_CTX  cert_ctx;
     235                 :            :         int i;
     236                 :          9 :         int ret = 1;
     237                 :            : 
     238                 :            :         /* chain is an out argument. */
     239                 :          9 :         *chain = NULL;
     240                 :          9 :         X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted);
     241                 :          9 :         X509_STORE_CTX_set_purpose(&cert_ctx, X509_PURPOSE_TIMESTAMP_SIGN);
     242                 :          9 :         i = X509_verify_cert(&cert_ctx);
     243         [ -  + ]:          9 :         if (i <= 0)
     244                 :            :                 {
     245                 :          0 :                 int j = X509_STORE_CTX_get_error(&cert_ctx);
     246                 :          0 :                 TSerr(TS_F_TS_VERIFY_CERT, TS_R_CERTIFICATE_VERIFY_ERROR);
     247                 :          0 :                 ERR_add_error_data(2, "Verify error:",
     248                 :            :                                    X509_verify_cert_error_string(j));
     249                 :          0 :                 ret = 0;
     250                 :            :                 }
     251                 :            :         else
     252                 :            :                 {
     253                 :            :                 /* Get a copy of the certificate chain. */
     254                 :          9 :                 *chain = X509_STORE_CTX_get1_chain(&cert_ctx);
     255                 :            :                 }
     256                 :            : 
     257                 :          9 :         X509_STORE_CTX_cleanup(&cert_ctx);
     258                 :            : 
     259                 :          9 :         return ret;
     260                 :            :         }
     261                 :            : 
     262                 :          9 : static int TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509) *chain)
     263                 :            :         {
     264                 :          9 :         ESS_SIGNING_CERT *ss = ESS_get_signing_cert(si);
     265                 :          9 :         STACK_OF(ESS_CERT_ID) *cert_ids = NULL;
     266                 :            :         X509 *cert;
     267                 :          9 :         int i = 0;
     268                 :          9 :         int ret = 0;
     269                 :            : 
     270         [ +  - ]:          9 :         if (!ss) goto err;
     271                 :          9 :         cert_ids = ss->cert_ids;
     272                 :            :         /* The signer certificate must be the first in cert_ids. */
     273                 :          9 :         cert = sk_X509_value(chain, 0);
     274         [ +  - ]:          9 :         if (TS_find_cert(cert_ids, cert) != 0) goto err;
     275                 :            :         
     276                 :            :         /* Check the other certificates of the chain if there are more
     277                 :            :            than one certificate ids in cert_ids. */
     278         [ +  - ]:          9 :         if (sk_ESS_CERT_ID_num(cert_ids) > 1)
     279                 :            :                 {
     280                 :            :                 /* All the certificates of the chain must be in cert_ids. */
     281         [ +  + ]:         18 :                 for (i = 1; i < sk_X509_num(chain); ++i)
     282                 :            :                         {
     283                 :          9 :                         cert = sk_X509_value(chain, i);
     284         [ +  - ]:          9 :                         if (TS_find_cert(cert_ids, cert) < 0) goto err;
     285                 :            :                         }
     286                 :            :                 }
     287                 :            :         ret = 1;
     288                 :            :  err:
     289         [ -  + ]:          9 :         if (!ret)
     290                 :          0 :                 TSerr(TS_F_TS_CHECK_SIGNING_CERTS, 
     291                 :            :                       TS_R_ESS_SIGNING_CERTIFICATE_ERROR);
     292                 :          9 :         ESS_SIGNING_CERT_free(ss);
     293                 :          9 :         return ret;
     294                 :            :         }
     295                 :            : 
     296                 :          9 : static ESS_SIGNING_CERT *ESS_get_signing_cert(PKCS7_SIGNER_INFO *si)
     297                 :            :         {
     298                 :            :         ASN1_TYPE *attr;
     299                 :            :         const unsigned char *p;
     300                 :          9 :         attr = PKCS7_get_signed_attribute(si, 
     301                 :            :                                           NID_id_smime_aa_signingCertificate);
     302         [ +  - ]:          9 :         if (!attr) return NULL;
     303                 :          9 :         p = attr->value.sequence->data;
     304                 :          9 :         return d2i_ESS_SIGNING_CERT(NULL, &p, attr->value.sequence->length);
     305                 :            :         }
     306                 :            : 
     307                 :            : /* Returns < 0 if certificate is not found, certificate index otherwise. */
     308                 :         18 : static int TS_find_cert(STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
     309                 :            :         {
     310                 :            :         int i;
     311                 :            : 
     312         [ +  - ]:         18 :         if (!cert_ids || !cert) return -1;
     313                 :            : 
     314                 :            :         /* Recompute SHA1 hash of certificate if necessary (side effect). */
     315                 :         18 :         X509_check_purpose(cert, -1, 0);
     316                 :            : 
     317                 :            :         /* Look for cert in the cert_ids vector. */
     318         [ +  - ]:         27 :         for (i = 0; i < sk_ESS_CERT_ID_num(cert_ids); ++i)
     319                 :            :                 {
     320                 :         27 :                 ESS_CERT_ID *cid = sk_ESS_CERT_ID_value(cert_ids, i);
     321                 :            : 
     322                 :            :                 /* Check the SHA-1 hash first. */
     323         [ +  - ]:         27 :                 if (cid->hash->length == sizeof(cert->sha1_hash)
     324         [ +  + ]:         27 :                     && !memcmp(cid->hash->data, cert->sha1_hash,
     325                 :            :                                sizeof(cert->sha1_hash)))
     326                 :            :                         {
     327                 :            :                         /* Check the issuer/serial as well if specified. */
     328                 :         18 :                         ESS_ISSUER_SERIAL *is = cid->issuer_serial;
     329 [ +  + ][ +  - ]:         18 :                         if (!is || !TS_issuer_serial_cmp(is, cert->cert_info))
     330                 :         18 :                                 return i;
     331                 :            :                         }
     332                 :            :                 }
     333                 :            :         
     334                 :            :         return -1;
     335                 :            :         }
     336                 :            : 
     337                 :          9 : static int TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509_CINF *cinfo)
     338                 :            :         {
     339                 :            :         GENERAL_NAME *issuer;
     340                 :            : 
     341 [ +  - ][ +  - ]:          9 :         if (!is || !cinfo || sk_GENERAL_NAME_num(is->issuer) != 1) return -1;
     342                 :            : 
     343                 :            :         /* Check the issuer first. It must be a directory name. */
     344                 :          9 :         issuer = sk_GENERAL_NAME_value(is->issuer, 0);
     345         [ +  - ]:          9 :         if (issuer->type != GEN_DIRNAME 
     346         [ +  - ]:          9 :             || X509_NAME_cmp(issuer->d.dirn, cinfo->issuer))
     347                 :            :                 return -1;
     348                 :            : 
     349                 :            :         /* Check the serial number, too. */
     350         [ +  - ]:          9 :         if (ASN1_INTEGER_cmp(is->serial, cinfo->serialNumber))
     351                 :            :                 return -1;
     352                 :            : 
     353                 :          9 :         return 0;
     354                 :            :         }
     355                 :            : 
     356                 :            : /*
     357                 :            :  * Verifies whether 'response' contains a valid response with regards 
     358                 :            :  * to the settings of the context:
     359                 :            :  *      - Gives an error message if the TS_TST_INFO is not present.
     360                 :            :  *      - Calls _TS_RESP_verify_token to verify the token content.
     361                 :            :  */
     362                 :          7 : int TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response)
     363                 :            :         {
     364                 :          7 :         PKCS7 *token = TS_RESP_get_token(response);
     365                 :          7 :         TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
     366                 :          7 :         int ret = 0;
     367                 :            : 
     368                 :            :         /* Check if we have a successful TS_TST_INFO object in place. */
     369         [ +  - ]:          7 :         if (!TS_check_status_info(response)) goto err;
     370                 :            : 
     371                 :            :         /* Check the contents of the time stamp token. */
     372         [ +  + ]:          7 :         if (!int_TS_RESP_verify_token(ctx, token, tst_info))
     373                 :            :                 goto err;
     374                 :            : 
     375                 :          4 :         ret = 1;
     376                 :            :  err:
     377                 :          7 :         return ret;
     378                 :            :         }
     379                 :            : 
     380                 :            : /*
     381                 :            :  * Tries to extract a TS_TST_INFO structure from the PKCS7 token and
     382                 :            :  * calls the internal int_TS_RESP_verify_token function for verifying it.
     383                 :            :  */
     384                 :          2 : int TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token)
     385                 :            :         {
     386                 :          2 :         TS_TST_INFO *tst_info = PKCS7_to_TS_TST_INFO(token);
     387                 :          2 :         int ret = 0;
     388         [ +  - ]:          2 :         if (tst_info)
     389                 :            :                 {
     390                 :          2 :                 ret = int_TS_RESP_verify_token(ctx, token, tst_info);
     391                 :          2 :                 TS_TST_INFO_free(tst_info);
     392                 :            :                 }
     393                 :          2 :         return ret;
     394                 :            :         }
     395                 :            : 
     396                 :            : /*
     397                 :            :  * Verifies whether the 'token' contains a valid time stamp token 
     398                 :            :  * with regards to the settings of the context. Only those checks are
     399                 :            :  * carried out that are specified in the context:
     400                 :            :  *      - Verifies the signature of the TS_TST_INFO.
     401                 :            :  *      - Checks the version number of the response.
     402                 :            :  *      - Check if the requested and returned policies math.
     403                 :            :  *      - Check if the message imprints are the same.
     404                 :            :  *      - Check if the nonces are the same.
     405                 :            :  *      - Check if the TSA name matches the signer.
     406                 :            :  *      - Check if the TSA name is the expected TSA.
     407                 :            :  */
     408                 :          9 : static int int_TS_RESP_verify_token(TS_VERIFY_CTX *ctx, 
     409                 :            :                                  PKCS7 *token, TS_TST_INFO *tst_info)
     410                 :            :         {
     411                 :          9 :         X509 *signer = NULL;
     412                 :          9 :         GENERAL_NAME *tsa_name = TS_TST_INFO_get_tsa(tst_info);
     413                 :          9 :         X509_ALGOR *md_alg = NULL;
     414                 :          9 :         unsigned char *imprint = NULL;
     415                 :          9 :         unsigned imprint_len = 0;
     416                 :          9 :         int ret = 0;
     417                 :            : 
     418                 :            :         /* Verify the signature. */
     419         [ +  - ]:          9 :         if ((ctx->flags & TS_VFY_SIGNATURE)
     420         [ +  - ]:          9 :             && !TS_RESP_verify_signature(token, ctx->certs, ctx->store,
     421                 :            :                                          &signer))
     422                 :            :                 goto err;
     423                 :            :         
     424                 :            :         /* Check version number of response. */
     425         [ +  - ]:          9 :         if ((ctx->flags & TS_VFY_VERSION)
     426         [ -  + ]:          9 :             && TS_TST_INFO_get_version(tst_info) != 1)
     427                 :            :                 {
     428                 :          0 :                 TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_UNSUPPORTED_VERSION);
     429                 :          0 :                 goto err;
     430                 :            :                 }
     431                 :            : 
     432                 :            :         /* Check policies. */
     433         [ +  + ]:          9 :         if ((ctx->flags & TS_VFY_POLICY)
     434         [ +  + ]:          5 :             && !TS_check_policy(ctx->policy, tst_info))
     435                 :            :                 goto err;
     436                 :            :         
     437                 :            :         /* Check message imprints. */
     438         [ +  + ]:          7 :         if ((ctx->flags & TS_VFY_IMPRINT)
     439         [ +  + ]:          4 :             && !TS_check_imprints(ctx->md_alg, ctx->imprint, ctx->imprint_len,
     440                 :            :                                   tst_info)) 
     441                 :            :                 goto err;
     442                 :            : 
     443                 :            :         /* Compute and check message imprints. */
     444         [ +  + ]:          6 :         if ((ctx->flags & TS_VFY_DATA)
     445         [ +  - ]:          3 :             && (!TS_compute_imprint(ctx->data, tst_info,
     446                 :            :                                     &md_alg, &imprint, &imprint_len)
     447         [ +  - ]:          3 :             || !TS_check_imprints(md_alg, imprint, imprint_len, tst_info)))
     448                 :            :                 goto err;
     449                 :            : 
     450                 :            :         /* Check nonces. */
     451         [ +  + ]:          6 :         if ((ctx->flags & TS_VFY_NONCE)
     452         [ +  - ]:          2 :             && !TS_check_nonces(ctx->nonce, tst_info))
     453                 :            :                 goto err;
     454                 :            : 
     455                 :            :         /* Check whether TSA name and signer certificate match. */
     456         [ +  - ]:          6 :         if ((ctx->flags & TS_VFY_SIGNER)
     457 [ +  - ][ -  + ]:          6 :             && tsa_name && !TS_check_signer_name(tsa_name, signer))
     458                 :            :                 {
     459                 :          0 :                 TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_TSA_NAME_MISMATCH);
     460                 :          0 :                 goto err;
     461                 :            :                 }
     462                 :            : 
     463                 :            :         /* Check whether the TSA is the expected one. */
     464         [ -  + ]:          6 :         if ((ctx->flags & TS_VFY_TSA_NAME)
     465         [ #  # ]:          0 :             && !TS_check_signer_name(ctx->tsa_name, signer))
     466                 :            :                 {
     467                 :          0 :                 TSerr(TS_F_INT_TS_RESP_VERIFY_TOKEN, TS_R_TSA_UNTRUSTED);
     468                 :          0 :                 goto err;
     469                 :            :                 }
     470                 :            : 
     471                 :            :         ret = 1;
     472                 :            :  err:
     473                 :          9 :         X509_free(signer);
     474                 :          9 :         X509_ALGOR_free(md_alg);
     475                 :          9 :         OPENSSL_free(imprint);
     476                 :          9 :         return ret;
     477                 :            :         }
     478                 :            : 
     479                 :          7 : static int TS_check_status_info(TS_RESP *response)
     480                 :            :         {
     481                 :          7 :         TS_STATUS_INFO *info = TS_RESP_get_status_info(response);
     482                 :          7 :         long status = ASN1_INTEGER_get(info->status);
     483                 :          7 :         const char *status_text = NULL;
     484                 :          7 :         char *embedded_status_text = NULL;
     485                 :          7 :         char failure_text[TS_STATUS_BUF_SIZE] = "";
     486                 :            : 
     487                 :            :         /* Check if everything went fine. */
     488         [ -  + ]:          7 :         if (status == 0 || status == 1) return 1;
     489                 :            : 
     490                 :            :         /* There was an error, get the description in status_text. */
     491         [ #  # ]:          0 :         if (0 <= status && status < (long)TS_STATUS_TEXT_SIZE)
     492                 :          0 :                 status_text = TS_status_text[status];
     493                 :            :         else
     494                 :            :                 status_text = "unknown code";
     495                 :            : 
     496                 :            :         /* Set the embedded_status_text to the returned description. */
     497         [ #  # ]:          0 :         if (sk_ASN1_UTF8STRING_num(info->text) > 0
     498         [ #  # ]:          0 :             && !(embedded_status_text = TS_get_status_text(info->text)))
     499                 :            :                 return 0;
     500                 :            :         
     501                 :            :         /* Filling in failure_text with the failure information. */
     502         [ #  # ]:          0 :         if (info->failure_info)
     503                 :            :                 {
     504                 :            :                 int i;
     505                 :            :                 int first = 1;
     506         [ #  # ]:          0 :                 for (i = 0; i < (int)TS_FAILURE_INFO_SIZE; ++i)
     507                 :            :                         {
     508         [ #  # ]:          0 :                         if (ASN1_BIT_STRING_get_bit(info->failure_info,
     509                 :            :                                                     TS_failure_info[i].code))
     510                 :            :                                 {
     511         [ #  # ]:          0 :                                 if (!first)
     512                 :            :                                         strcpy(failure_text, ",");
     513                 :            :                                 else
     514                 :            :                                         first = 0;
     515                 :          0 :                                 strcat(failure_text, TS_failure_info[i].text);
     516                 :            :                                 }
     517                 :            :                         }
     518                 :            :                 }
     519         [ #  # ]:          0 :         if (failure_text[0] == '\0')
     520                 :            :                 strcpy(failure_text, "unspecified");
     521                 :            : 
     522                 :            :         /* Making up the error string. */
     523                 :          0 :         TSerr(TS_F_TS_CHECK_STATUS_INFO, TS_R_NO_TIME_STAMP_TOKEN);
     524         [ #  # ]:          0 :         ERR_add_error_data(6,
     525                 :            :                            "status code: ", status_text,
     526                 :            :                            ", status text: ", embedded_status_text ? 
     527                 :            :                            embedded_status_text : "unspecified",
     528                 :            :                            ", failure codes: ", failure_text);
     529                 :          0 :         OPENSSL_free(embedded_status_text);
     530                 :            : 
     531                 :          0 :         return 0;
     532                 :            :         }
     533                 :            : 
     534                 :          0 : static char *TS_get_status_text(STACK_OF(ASN1_UTF8STRING) *text)
     535                 :            :         {
     536                 :            :         int i;
     537                 :          0 :         unsigned int length = 0;
     538                 :          0 :         char *result = NULL;
     539                 :            :         char *p;
     540                 :            : 
     541                 :            :         /* Determine length first. */
     542         [ #  # ]:          0 :         for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i)
     543                 :            :                 {
     544                 :          0 :                 ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i);
     545                 :          0 :                 length += ASN1_STRING_length(current);
     546                 :          0 :                 length += 1;    /* separator character */
     547                 :            :                 }
     548                 :            :         /* Allocate memory (closing '\0' included). */
     549         [ #  # ]:          0 :         if (!(result = OPENSSL_malloc(length)))
     550                 :            :                 {
     551                 :          0 :                 TSerr(TS_F_TS_GET_STATUS_TEXT, ERR_R_MALLOC_FAILURE);
     552                 :          0 :                 return NULL;
     553                 :            :                 }
     554                 :            :         /* Concatenate the descriptions. */
     555         [ #  # ]:          0 :         for (i = 0, p = result; i < sk_ASN1_UTF8STRING_num(text); ++i)
     556                 :            :                 {
     557                 :          0 :                 ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i);
     558                 :          0 :                 length = ASN1_STRING_length(current);
     559         [ #  # ]:          0 :                 if (i > 0) *p++ = '/';
     560                 :          0 :                 strncpy(p, (const char *)ASN1_STRING_data(current), length);
     561                 :          0 :                 p += length;
     562                 :            :                 }
     563                 :            :         /* We do have space for this, too. */
     564                 :          0 :         *p = '\0';
     565                 :            :         
     566                 :          0 :         return result;
     567                 :            :         }
     568                 :            : 
     569                 :          5 : static int TS_check_policy(ASN1_OBJECT *req_oid, TS_TST_INFO *tst_info)
     570                 :            :         {
     571                 :          5 :         ASN1_OBJECT *resp_oid = TS_TST_INFO_get_policy_id(tst_info);
     572                 :            : 
     573         [ +  + ]:          5 :         if (OBJ_cmp(req_oid, resp_oid) != 0)
     574                 :            :                 {
     575                 :          2 :                 TSerr(TS_F_TS_CHECK_POLICY, TS_R_POLICY_MISMATCH);
     576                 :          2 :                 return 0;
     577                 :            :                 }
     578                 :            : 
     579                 :            :         return 1;
     580                 :            :         }
     581                 :            : 
     582                 :          3 : static int TS_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
     583                 :            :                               X509_ALGOR **md_alg, 
     584                 :            :                               unsigned char **imprint, unsigned *imprint_len)
     585                 :            :         {
     586                 :          3 :         TS_MSG_IMPRINT *msg_imprint = TS_TST_INFO_get_msg_imprint(tst_info);
     587                 :          3 :         X509_ALGOR *md_alg_resp = TS_MSG_IMPRINT_get_algo(msg_imprint);
     588                 :            :         const EVP_MD *md;
     589                 :            :         EVP_MD_CTX md_ctx;
     590                 :            :         unsigned char buffer[4096];
     591                 :            :         int length;
     592                 :            : 
     593                 :          3 :         *md_alg = NULL;
     594                 :          3 :         *imprint = NULL;
     595                 :            : 
     596                 :            :         /* Return the MD algorithm of the response. */
     597         [ +  - ]:          3 :         if (!(*md_alg = X509_ALGOR_dup(md_alg_resp))) goto err;
     598                 :            : 
     599                 :            :         /* Getting the MD object. */
     600         [ -  + ]:          3 :         if (!(md = EVP_get_digestbyobj((*md_alg)->algorithm)))
     601                 :            :                 {
     602                 :          0 :                 TSerr(TS_F_TS_COMPUTE_IMPRINT, TS_R_UNSUPPORTED_MD_ALGORITHM);
     603                 :          0 :                 goto err;
     604                 :            :                 }
     605                 :            : 
     606                 :            :         /* Compute message digest. */
     607                 :          3 :         length = EVP_MD_size(md);
     608         [ +  - ]:          3 :         if (length < 0)
     609                 :            :             goto err;
     610                 :          3 :         *imprint_len = length;
     611         [ -  + ]:          3 :         if (!(*imprint = OPENSSL_malloc(*imprint_len))) 
     612                 :            :                 {
     613                 :          0 :                 TSerr(TS_F_TS_COMPUTE_IMPRINT, ERR_R_MALLOC_FAILURE);
     614                 :          0 :                 goto err;
     615                 :            :                 }
     616                 :            : 
     617         [ +  - ]:          3 :         if (!EVP_DigestInit(&md_ctx, md))
     618                 :            :                 goto err;
     619         [ +  + ]:          9 :         while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0)
     620                 :            :                 {
     621         [ +  - ]:          9 :                 if (!EVP_DigestUpdate(&md_ctx, buffer, length))
     622                 :            :                         goto err;
     623                 :            :                 }
     624         [ -  + ]:          3 :         if (!EVP_DigestFinal(&md_ctx, *imprint, NULL))
     625                 :            :                 goto err;
     626                 :            : 
     627                 :            :         return 1;
     628                 :            :  err:
     629                 :          0 :         X509_ALGOR_free(*md_alg);
     630                 :          0 :         OPENSSL_free(*imprint);
     631                 :          0 :         *imprint_len = 0;
     632                 :          0 :         *imprint = 0;
     633                 :          0 :         return 0;
     634                 :            :         }
     635                 :            : 
     636                 :          7 : static int TS_check_imprints(X509_ALGOR *algor_a, 
     637                 :            :                              unsigned char *imprint_a, unsigned len_a,
     638                 :            :                              TS_TST_INFO *tst_info)
     639                 :            :         {
     640                 :          7 :         TS_MSG_IMPRINT *b = TS_TST_INFO_get_msg_imprint(tst_info);
     641                 :          7 :         X509_ALGOR *algor_b = TS_MSG_IMPRINT_get_algo(b);
     642                 :          7 :         int ret = 0;
     643                 :            : 
     644                 :            :         /* algor_a is optional. */
     645         [ +  - ]:          7 :         if (algor_a)
     646                 :            :                 {
     647                 :            :                 /* Compare algorithm OIDs. */
     648         [ +  - ]:          7 :                 if (OBJ_cmp(algor_a->algorithm, algor_b->algorithm)) goto err;
     649                 :            : 
     650                 :            :                 /* The parameter must be NULL in both. */
     651         [ +  - ]:          7 :                 if ((algor_a->parameter 
     652         [ +  - ]:          7 :                      && ASN1_TYPE_get(algor_a->parameter) != V_ASN1_NULL)
     653         [ +  - ]:          7 :                     || (algor_b->parameter
     654         [ +  - ]:          7 :                         && ASN1_TYPE_get(algor_b->parameter) != V_ASN1_NULL))
     655                 :            :                         goto err;
     656                 :            :                 }
     657                 :            : 
     658                 :            :         /* Compare octet strings. */
     659   [ +  -  +  + ]:         14 :         ret = len_a == (unsigned) ASN1_STRING_length(b->hashed_msg) &&
     660                 :          7 :                 memcmp(imprint_a, ASN1_STRING_data(b->hashed_msg), len_a) == 0;
     661                 :            :  err:
     662         [ +  + ]:          7 :         if (!ret)
     663                 :          1 :                 TSerr(TS_F_TS_CHECK_IMPRINTS, TS_R_MESSAGE_IMPRINT_MISMATCH);
     664                 :          7 :         return ret;
     665                 :            :         }
     666                 :            : 
     667                 :          2 : static int TS_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info)
     668                 :            :         {
     669                 :          2 :         const ASN1_INTEGER *b = TS_TST_INFO_get_nonce(tst_info);
     670                 :            : 
     671                 :            :         /* Error if nonce is missing. */
     672         [ -  + ]:          2 :         if (!b)
     673                 :            :                 {
     674                 :          0 :                 TSerr(TS_F_TS_CHECK_NONCES, TS_R_NONCE_NOT_RETURNED);
     675                 :          0 :                 return 0;
     676                 :            :                 }
     677                 :            : 
     678                 :            :         /* No error if a nonce is returned without being requested. */
     679         [ -  + ]:          2 :         if (ASN1_INTEGER_cmp(a, b) != 0)
     680                 :            :                 {
     681                 :          0 :                 TSerr(TS_F_TS_CHECK_NONCES, TS_R_NONCE_MISMATCH);
     682                 :          0 :                 return 0;
     683                 :            :                 }
     684                 :            : 
     685                 :            :         return 1;
     686                 :            :         }
     687                 :            : 
     688                 :            : /* Check if the specified TSA name matches either the subject
     689                 :            :    or one of the subject alternative names of the TSA certificate. */
     690                 :          6 : static int TS_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer)
     691                 :            :         {
     692                 :          6 :         STACK_OF(GENERAL_NAME) *gen_names = NULL;
     693                 :          6 :         int idx = -1;
     694                 :          6 :         int found = 0;
     695                 :            : 
     696                 :            :         /* Check the subject name first. */
     697         [ +  - ]:          6 :         if (tsa_name->type == GEN_DIRNAME 
     698         [ -  + ]:          6 :             && X509_name_cmp(tsa_name->d.dirn, signer->cert_info->subject) == 0)
     699                 :            :                 return 1;
     700                 :            : 
     701                 :            :         /* Check all the alternative names. */
     702                 :          0 :         gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name,
     703                 :            :                                      NULL, &idx);
     704         [ #  # ]:          0 :         while (gen_names != NULL
     705         [ #  # ]:          0 :                && !(found = TS_find_name(gen_names, tsa_name) >= 0))
     706                 :            :                 {
     707                 :            :                 /* Get the next subject alternative name,
     708                 :            :                    although there should be no more than one. */
     709                 :          0 :                 GENERAL_NAMES_free(gen_names);
     710                 :          0 :                 gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name,
     711                 :            :                                              NULL, &idx);
     712                 :            :                 }
     713         [ #  # ]:          0 :         if (gen_names) GENERAL_NAMES_free(gen_names);
     714                 :            :         
     715                 :          0 :         return found;
     716                 :            :         }
     717                 :            : 
     718                 :            : /* Returns 1 if name is in gen_names, 0 otherwise. */
     719                 :          0 : static int TS_find_name(STACK_OF(GENERAL_NAME) *gen_names, GENERAL_NAME *name)
     720                 :            :         {
     721                 :            :         int i, found;
     722 [ #  # ][ #  # ]:          0 :         for (i = 0, found = 0; !found && i < sk_GENERAL_NAME_num(gen_names);
     723                 :          0 :              ++i)
     724                 :            :                 {
     725                 :          0 :                 GENERAL_NAME *current = sk_GENERAL_NAME_value(gen_names, i);
     726                 :          0 :                 found = GENERAL_NAME_cmp(current, name) == 0;
     727                 :            :                 }
     728         [ #  # ]:          0 :         return found ? i - 1 : -1;
     729                 :            :         }

Generated by: LCOV version 1.9