libclamav/crtmgr.c
5d49bd06
 /*
e7f5f537
  *  Copyright (C) 2013-2021 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
52cddcbc
  *  Copyright (C) 2011-2013 Sourcefire, Inc.
5d49bd06
  *
  *  Authors: aCaB
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  *  MA 02110-1301, USA.
  */
 
8997495d
 #if HAVE_CONFIG_H
 #include "clamav-config.h"
 #endif
 
60d8d2c3
 #include "clamav.h"
8997495d
 #include "others.h"
56b4f4b0
 #include "crtmgr.h"
e5c6c1aa
 
1b5c9f72
 #define OID_1_2_840_113549_2_5 "\x2a\x86\x48\x86\xf7\x0d\x02\x05"
 #define OID_md5 OID_1_2_840_113549_2_5
 
 #define OID_1_3_14_3_2_26 "\x2b\x0e\x03\x02\x1a"
 #define OID_sha1 OID_1_3_14_3_2_26
 
 #define OID_2_16_840_1_101_3_4_2_1 "\x60\x86\x48\x01\x65\x03\x04\x02\x01"
 #define OID_sha256 OID_2_16_840_1_101_3_4_2_1
 
d3440d85
 #define OID_2_16_840_1_101_3_4_2_2 "\x60\x86\x48\x01\x65\x03\x04\x02\x02"
 #define OID_sha384 OID_2_16_840_1_101_3_4_2_2
 
0973eb97
 #define OID_2_16_840_1_101_3_4_2_3 "\x60\x86\x48\x01\x65\x03\x04\x02\x03"
 #define OID_sha512 OID_2_16_840_1_101_3_4_2_3
 
72fd33c8
 int cli_crt_init(cli_crt *x509)
 {
71da61a7
     int ret;
d74d0386
 
     memset(x509, 0, sizeof(*x509));
 
72fd33c8
     if ((ret = mp_init_multi(&x509->n, &x509->e, &x509->sig, NULL))) {
50873c8a
         cli_errmsg("cli_crt_init: mp_init_multi failed with %d\n", ret);
         return 1;
71da61a7
     }
e5c6c1aa
     return 0;
 }
 
72fd33c8
 void cli_crt_clear(cli_crt *x509)
 {
cd94be7a
     UNUSEDPARAM(x509);
e5c6c1aa
     mp_clear_multi(&x509->n, &x509->e, &x509->sig, NULL);
 }
 
50d1a0b6
 /* Look for an existing certificate in the trust store m.  This search allows
  * the not_before / not_after / certSign / codeSign / timeSign fields to be
  * more restrictive than the values associated with a cert in the trust store,
  * but not less.  It's probably overkill to not do exact matching on those
  * fields... TODO Is there a case where this is needed
  *
  * There are two ways that things get added to the whitelist - through the CRB
  * rules, and through embedded signatures / catalog files that we parse.  CRB
3cf1b1c5
  * rules don't currently allow the issuer and hashtype to be specified, so the
21588dc9
  * code sets those to sentinel values (0xca repeating and CLI_HASHTYPE_ANY
  * respectively). Also, the exponent field gets set to a fixed value for CRB
  * rules, and the serial number field is allowed to be empty as well (in this
  * case it will get set to 0xca repeating).
  *
  * There are two ways we'd like to use this function:
206dbaef
  *
3cf1b1c5
  *  - To see whether x509 already exists in m (when adding new CRB sig certs
a0980389
  *    and when adding certs that are embedded in Authenticode signatures) to
  *    prevent duplicate entries. In this case, we want to take x509's
21588dc9
  *    hashtype, issuer, serial, and exponent field into account, so a CRB sig
  *    cert entry isn't returned for an embedded cert duplicate check, and so
  *    that two embedded certs with different hash types, issuers, serials, or
  *    exponents aren't treated as being the same. A non-NULL return when used
  *    this way means that the cert need not be added to the trust store.
206dbaef
  *
3cf1b1c5
  *  - To see whether a CRB sig matches against x509, deeming it worthy to be
a0980389
  *    added to the trust store.  In this case, we don't want to compare
  *    hashtype and issuer, since the embedded sig will have the actual values
21588dc9
  *    and the CRB sig cert will have placeholder values. A non-NULL return
  *    value when used this way means that the cert doesn't match against an
  *    existing CRB rule and should not be added to the trust store.
206dbaef
  *
3cf1b1c5
  * Use crb_crts_only to distinguish between the two cases.  If True, it will
  * ignore all crts not added from CRB rules and ignore x509's issuer and
21588dc9
  * hashtype fields.
  *
  */
3cf1b1c5
 cli_crt *crtmgr_whitelist_lookup(crtmgr *m, cli_crt *x509, int crb_crts_only)
72fd33c8
 {
f05aa165
     cli_crt *i;
72fd33c8
     for (i = m->crts; i; i = i->next) {
3cf1b1c5
 
         if (i->isBlacklisted) {
             continue;
         }
 
         if (crb_crts_only) {
             if (i->hashtype != CLI_HASHTYPE_ANY) {
                 continue;
             }
         } else {
             /* Almost all of the rules in m will be CRB rules, so optimize for
              * the case where we are trying to determine whether an embedded
              * cert already exists in m (by checking the hashtype first). Do
21588dc9
              * the other non-CRB rule cert checks here too to simplify the
              * code. */
3cf1b1c5
 
             if (x509->hashtype != i->hashtype ||
21588dc9
                 memcmp(x509->issuer, i->issuer, sizeof(i->issuer)) ||
                 x509->ignore_serial != i->ignore_serial ||
                 mp_cmp(&x509->e, &i->e)) {
                 continue;
             }
         }
 
         if (!i->ignore_serial) {
             if (memcmp(x509->serial, i->serial, sizeof(i->serial))) {
3cf1b1c5
                 continue;
             }
         }
 
         if (x509->not_before >= i->not_before &&
72fd33c8
             x509->not_after <= i->not_after &&
             (i->certSign | x509->certSign) == i->certSign &&
             (i->codeSign | x509->codeSign) == i->codeSign &&
             (i->timeSign | x509->timeSign) == i->timeSign &&
             !memcmp(x509->subject, i->subject, sizeof(i->subject)) &&
21588dc9
             !mp_cmp(&x509->n, &i->n)) {
50873c8a
             return i;
         }
8997495d
     }
71da61a7
     return NULL;
 }
 
72fd33c8
 cli_crt *crtmgr_blacklist_lookup(crtmgr *m, cli_crt *x509)
 {
f05aa165
     cli_crt *i;
50d1a0b6
     for (i = m->crts; i; i = i->next) {
21588dc9
         /* The CRB rules are based on subject, serial, and public key,
          * so do blacklist lookups based on those fields. The serial
          * number field can also be blank, which effectively blacklists
          * all possible serial numbers using the specified subject and
          * public key. Sometimes when people go to have their cert
          * renewed, they'll opt to have the subject and public key be
          * the same, but the CA must issue a new serial number for the
          * new cert. A blank issuer in a CRB rule allows blacklisting
          * all of these at once. */
2c2e89e1
 
92088f91
         // TODO the rule format specifies CodeSign / TimeSign / CertSign
         // which we could also match on, but we just ignore those fields
         // for blacklist certs for now
 
67f3d97d
         // TODO the rule format allows the exponent to be specified as well,
         // but that gets ignored when CRB rules are parsed (and set to a fixed
         // value), so ignore that field when looking at certs
 
21588dc9
         if (!i->isBlacklisted ||
             memcmp(i->subject, x509->subject, sizeof(i->subject)) ||
             mp_cmp(&x509->n, &i->n)) {
             continue;
         }
50873c8a
 
21588dc9
         if (!i->ignore_serial) {
             if (memcmp(i->serial, x509->serial, sizeof(i->serial))) {
                 continue;
             }
50d1a0b6
         }
21588dc9
         return i;
50d1a0b6
     }
     return NULL;
 }
50873c8a
 
50d1a0b6
 /* Determine whether x509 already exists in m. The fields compared depend on
  * whether x509 is a blacklist entry or a trusted certificate */
72fd33c8
 cli_crt *crtmgr_lookup(crtmgr *m, cli_crt *x509)
 {
50d1a0b6
     if (x509->isBlacklisted) {
         return crtmgr_blacklist_lookup(m, x509);
     } else {
3cf1b1c5
         return crtmgr_whitelist_lookup(m, x509, 0);
50d1a0b6
     }
 }
 
72fd33c8
 int crtmgr_add(crtmgr *m, cli_crt *x509)
 {
50d1a0b6
     cli_crt *i;
     int ret = 0;
 
     if (x509->isBlacklisted) {
         if (crtmgr_blacklist_lookup(m, x509)) {
             cli_dbgmsg("crtmgr_add: duplicate blacklist entry detected - not adding\n");
             return 0;
         }
     } else {
3cf1b1c5
         if (crtmgr_whitelist_lookup(m, x509, 0)) {
50d1a0b6
             cli_dbgmsg("crtmgr_add: duplicate trusted certificate detected - not adding\n");
             return 0;
50873c8a
         }
f05aa165
     }
7bcfb2f3
 
8997495d
     i = cli_malloc(sizeof(*i));
72fd33c8
     if (!i)
50873c8a
         return 1;
8997495d
 
72fd33c8
     if ((ret = mp_init_multi(&i->n, &i->e, &i->sig, NULL))) {
50873c8a
         cli_warnmsg("crtmgr_add: failed to mp_init failed with %d\n", ret);
         free(i);
         return 1;
8997495d
     }
72fd33c8
     if ((ret = mp_copy(&x509->n, &i->n)) || (ret = mp_copy(&x509->e, &i->e)) || (ret = mp_copy(&x509->sig, &i->sig))) {
50873c8a
         cli_warnmsg("crtmgr_add: failed to mp_init failed with %d\n", ret);
         cli_crt_clear(i);
         free(i);
         return 1;
8997495d
     }
0f418a13
 
     if ((x509->name))
50873c8a
         i->name = strdup(x509->name);
0f418a13
     else
50873c8a
         i->name = NULL;
0f418a13
 
616c0259
     memcpy(i->raw_subject, x509->raw_subject, sizeof(i->raw_subject));
     memcpy(i->raw_issuer, x509->raw_issuer, sizeof(i->raw_issuer));
     memcpy(i->raw_serial, x509->raw_serial, sizeof(i->raw_serial));
8997495d
     memcpy(i->subject, x509->subject, sizeof(i->subject));
a8e79d93
     memcpy(i->serial, x509->serial, sizeof(i->serial));
8997495d
     memcpy(i->issuer, x509->issuer, sizeof(i->issuer));
7bcfb2f3
     memcpy(i->tbshash, x509->tbshash, sizeof(i->tbshash));
21588dc9
     i->ignore_serial = x509->ignore_serial;
72fd33c8
     i->not_before    = x509->not_before;
     i->not_after     = x509->not_after;
     i->hashtype      = x509->hashtype;
     i->certSign      = x509->certSign;
     i->codeSign      = x509->codeSign;
     i->timeSign      = x509->timeSign;
278b2b28
     i->isBlacklisted = x509->isBlacklisted;
72fd33c8
     i->next          = m->crts;
     i->prev          = NULL;
     if (m->crts)
50873c8a
         m->crts->prev = i;
8997495d
     m->crts = i;
71da61a7
 
7bcfb2f3
     m->items++;
8997495d
     return 0;
 }
 
72fd33c8
 void crtmgr_init(crtmgr *m)
 {
     m->crts  = NULL;
7bcfb2f3
     m->items = 0;
 }
 
72fd33c8
 void crtmgr_del(crtmgr *m, cli_crt *x509)
 {
7bcfb2f3
     cli_crt *i;
72fd33c8
     for (i = m->crts; i; i = i->next) {
         if (i == x509) {
             if (i->prev)
50873c8a
                 i->prev->next = i->next;
             else
                 m->crts = i->next;
72fd33c8
             if (i->next)
50873c8a
                 i->next->prev = i->prev;
             cli_crt_clear(x509);
             if ((x509->name))
                 free(x509->name);
             free(x509);
             m->items--;
             return;
         }
7bcfb2f3
     }
 }
71da61a7
 
72fd33c8
 void crtmgr_free(crtmgr *m)
 {
     while (m->items)
50873c8a
         crtmgr_del(m, m->crts);
6bc5d0cb
 }
29fb5f5c
 
72fd33c8
 static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashtype, const uint8_t *refhash)
 {
29fb5f5c
     int keylen = mp_unsigned_bin_size(&x509->n), siglen = mp_unsigned_bin_size(sig);
1b5c9f72
     int ret, j, objlen, hashlen;
71da61a7
     uint8_t d[513];
     mp_int x;
 
1b5c9f72
     if (hashtype == CLI_SHA1RSA) {
         hashlen = SHA1_HASH_SIZE;
     } else if (hashtype == CLI_MD5RSA) {
         hashlen = MD5_HASH_SIZE;
     } else if (hashtype == CLI_SHA256RSA) {
         hashlen = SHA256_HASH_SIZE;
d3440d85
     } else if (hashtype == CLI_SHA384RSA) {
         hashlen = SHA384_HASH_SIZE;
0973eb97
     } else if (hashtype == CLI_SHA512RSA) {
         hashlen = SHA512_HASH_SIZE;
1b5c9f72
     } else {
d3440d85
         cli_errmsg("crtmgr_rsa_verify: Unsupported hashtype: %d\n", hashtype);
1b5c9f72
         return 1;
     }
 
72fd33c8
     if ((ret = mp_init(&x))) {
50873c8a
         cli_errmsg("crtmgr_rsa_verify: mp_init failed with %d\n", ret);
         return 1;
71da61a7
     }
29fb5f5c
 
     do {
72fd33c8
         if (MAX(keylen, siglen) - MIN(keylen, siglen) > 1) {
a2bb4cdf
             cli_dbgmsg("crtmgr_rsa_verify: keylen and siglen differ by more than one\n");
50873c8a
             break;
a2bb4cdf
         }
72fd33c8
         if ((ret = mp_exptmod(sig, &x509->e, &x509->n, &x))) {
50873c8a
             cli_warnmsg("crtmgr_rsa_verify: verification failed: mp_exptmod failed with %d\n", ret);
             break;
         }
72fd33c8
         if (mp_unsigned_bin_size(&x) != keylen - 1) {
a2bb4cdf
             cli_dbgmsg("crtmgr_rsa_verify: keylen-1 doesn't match expected size of exptmod result\n");
50873c8a
             break;
a2bb4cdf
         }
72fd33c8
         if (((unsigned int)mp_unsigned_bin_size(&x)) > sizeof(d)) {
a2bb4cdf
             cli_dbgmsg("crtmgr_rsa_verify: exptmod result would overrun working buffer\n");
d3440d85
             break;
a2bb4cdf
         }
72fd33c8
         if ((ret = mp_to_unsigned_bin(&x, d))) {
50873c8a
             cli_warnmsg("crtmgr_rsa_verify: mp_unsigned_bin_size failed with %d\n", ret);
             break;
         }
72fd33c8
         if (*d != 1) { /* block type 1 */
a2bb4cdf
             cli_dbgmsg("crtmgr_rsa_verify: expected block type 1 at d[0]\n");
50873c8a
             break;
a2bb4cdf
         }
50873c8a
 
         keylen -= 1; /* 0xff padding */
72fd33c8
         for (j = 1; j < keylen - 2; j++)
             if (d[j] != 0xff)
50873c8a
                 break;
72fd33c8
         if (j == keylen - 2) {
a2bb4cdf
             cli_dbgmsg("crtmgr_rsa_verify: only encountered 0xFF padding parsing cert\n");
50873c8a
             break;
a2bb4cdf
         }
72fd33c8
         if (d[j] != 0) { /* 0x00 separator */
a2bb4cdf
             cli_dbgmsg("crtmgr_rsa_verify: expected 0x00 separator\n");
50873c8a
             break;
a2bb4cdf
         }
50873c8a
 
         j++;
         keylen -= j; /* asn1 size */
 
72fd33c8
         if (keylen < hashlen) {
a2bb4cdf
             cli_dbgmsg("crtmgr_rsa_verify: encountered keylen less than hashlen\n");
50873c8a
             break;
a2bb4cdf
         }
72fd33c8
         if (keylen > hashlen) {
50873c8a
             /* hash is asn1 der encoded */
             /* SEQ { SEQ { OID, NULL }, OCTET STRING */
72fd33c8
             if (keylen < 2 || d[j] != 0x30 || d[j + 1] + 2 != keylen) {
a2bb4cdf
                 cli_dbgmsg("crtmgr_rsa_verify: unexpected hash to be ASN1 DER encoded\n");
50873c8a
                 break;
a2bb4cdf
             }
50873c8a
             keylen -= 2;
72fd33c8
             j += 2;
50873c8a
 
72fd33c8
             if (keylen < 2 || d[j] != 0x30) {
a2bb4cdf
                 cli_dbgmsg("crtmgr_rsa_verify: expected SEQUENCE at beginning of cert AlgorithmIdentifier\n");
50873c8a
                 break;
a2bb4cdf
             }
50873c8a
 
72fd33c8
             objlen = d[j + 1];
50873c8a
 
             keylen -= 2;
72fd33c8
             j += 2;
             if (keylen < objlen) {
a2bb4cdf
                 cli_dbgmsg("crtmgr_rsa_verify: key length mismatch in ASN1 DER hash encoding\n");
50873c8a
                 break;
a2bb4cdf
             }
72fd33c8
             if (objlen == 9) {
1b5c9f72
                 // Check for OID type indicating a length of 5, OID_sha1, and the NULL type/value
72fd33c8
                 if (hashtype != CLI_SHA1RSA || memcmp(&d[j], "\x06\x05" OID_sha1 "\x05\x00", 9)) {
50873c8a
                     cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
                     break;
                 }
72fd33c8
             } else if (objlen == 12) {
1b5c9f72
                 // Check for OID type indicating a length of 8, OID_md5, and the NULL type/value
72fd33c8
                 if (hashtype != CLI_MD5RSA || memcmp(&d[j], "\x06\x08" OID_md5 "\x05\x00", 12)) {
50873c8a
                     cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
                     break;
                 }
72fd33c8
             } else if (objlen == 13) {
d3440d85
                 if (hashtype == CLI_SHA256RSA) {
                     // Check for OID type indicating a length of 9, OID_sha256, and the NULL type/value
                     if (0 != memcmp(&d[j], "\x06\x09" OID_sha256 "\x05\x00", 13)) {
                         cli_dbgmsg("crtmgr_rsa_verify: invalid AlgorithmIdentifier block for SHA256 hash\n");
                         break;
                     }
 
                 } else if (hashtype == CLI_SHA384RSA) {
                     // Check for OID type indicating a length of 9, OID_sha384, and the NULL type/value
                     if (0 != memcmp(&d[j], "\x06\x09" OID_sha384 "\x05\x00", 13)) {
                         cli_dbgmsg("crtmgr_rsa_verify: invalid AlgorithmIdentifier block for SHA384 hash\n");
                         break;
                     }
 
0973eb97
                 } else if (hashtype == CLI_SHA512RSA) {
                     // Check for OID type indicating a length of 9, OID_sha512, and the NULL type/value
                     if (0 != memcmp(&d[j], "\x06\x09" OID_sha512 "\x05\x00", 13)) {
                         cli_dbgmsg("crtmgr_rsa_verify: invalid AlgorithmIdentifier block for SHA512 hash\n");
                         break;
                     }
 
d3440d85
                 } else {
50873c8a
                     cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
                     break;
                 }
             } else {
                 cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
                 break;
             }
 
             keylen -= objlen;
             j += objlen;
72fd33c8
             if (keylen < 2 || d[j] != 0x04 || d[j + 1] != hashlen) {
a2bb4cdf
                 cli_dbgmsg("crtmgr_rsa_verify: hash length mismatch in ASN1 DER hash encoding\n");
50873c8a
                 break;
a2bb4cdf
             }
50873c8a
             keylen -= 2;
72fd33c8
             j += 2;
             if (keylen != hashlen) {
a2bb4cdf
                 cli_dbgmsg("crtmgr_rsa_verify: extra data in the ASN1 DER hash encoding\n");
50873c8a
                 break;
a2bb4cdf
             }
50873c8a
         }
72fd33c8
         if (memcmp(&d[j], refhash, hashlen)) {
a2bb4cdf
             // This is a common error case if we are using crtmgr_rsa_verify to
             // determine whether we've found the right issuer certificate based
             // (as is done by crtmgr_verify_crt).  If we are pretty sure that
             // x509 is the correct cert to use for verification, then this
             // case is more of a concern.
50873c8a
             break;
a2bb4cdf
         }
50873c8a
 
         mp_clear(&x);
         return 0;
29fb5f5c
 
72fd33c8
     } while (0);
5e84efeb
 
29fb5f5c
     mp_clear(&x);
     return 1;
 }
 
3cf1b1c5
 /* For a given cli_crt, returns a pointer to the signer x509 certificate if
a2bb4cdf
  * one is found in the crtmgr and it's signature can be validated (NULL is
  * returned otherwise.) */
72fd33c8
 cli_crt *crtmgr_verify_crt(crtmgr *m, cli_crt *x509)
 {
f5092717
     cli_crt *i = m->crts, *best = NULL;
72fd33c8
     int score             = 0;
50d1a0b6
     unsigned int possible = 0;
29fb5f5c
 
92088f91
     // Loop through each of the certificates in our trust store and see whether
     // x509 is signed with it.  If it is, it's trusted
 
50d1a0b6
     // TODO Technically we should loop through all of the blacklisted certs
     // first to see whether one of those is used to sign x509.  This case
     // will get handled if the blacklisted certificate is embedded, since we
     // will call crtmgr_verify_crt on it and match against the blacklist entry
     // that way, but the cert doesn't HAVE to be embedded.  This case seems
92088f91
     // unlikely enough to ignore, though.  If we ever want to blacklist a
     // stolen CA cert or something, then we will need to revisit this.
50d1a0b6
 
72fd33c8
     for (i = m->crts; i; i = i->next) {
         if (i->certSign &&
             !i->isBlacklisted &&
             !memcmp(i->subject, x509->issuer, sizeof(i->subject)) &&
             !crtmgr_rsa_verify(i, &x509->sig, x509->hashtype, x509->tbshash)) {
50873c8a
             int curscore;
72fd33c8
             if ((x509->codeSign & i->codeSign) == x509->codeSign && (x509->timeSign & i->timeSign) == x509->timeSign)
50873c8a
                 return i;
50d1a0b6
             possible++;
50873c8a
             curscore = (x509->codeSign & i->codeSign) + (x509->timeSign & i->timeSign);
72fd33c8
             if (curscore > score) {
                 best  = i;
50873c8a
                 score = curscore;
             }
         }
71da61a7
     }
50d1a0b6
 
     if (possible > 1) {
         // If this is ever triggered, it's probably an indication of an error
         // in the CRB being used.
         cli_warnmsg("crtmgr_verify_crt: choosing between codeSign cert and timeSign cert without enough info - errors may result\n");
     }
f5092717
     return best;
71da61a7
 }
 
72fd33c8
 cli_crt *crtmgr_verify_pkcs7(crtmgr *m, const uint8_t *issuer, const uint8_t *serial, const void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash, cli_vrfy_type vrfytype)
 {
29fb5f5c
     cli_crt *i;
     mp_int sig;
     int ret;
 
72fd33c8
     if (signature_len < 1024 / 8 || signature_len > 4096 / 8 + 1) {
50873c8a
         cli_dbgmsg("crtmgr_verify_pkcs7: unsupported sig len: %u\n", signature_len);
         return NULL;
29fb5f5c
     }
72fd33c8
     if ((ret = mp_init(&sig))) {
a2bb4cdf
         cli_dbgmsg("crtmgr_verify_pkcs7: mp_init failed with %d\n", ret);
50873c8a
         return NULL;
29fb5f5c
     }
 
72fd33c8
     if ((ret = mp_read_unsigned_bin(&sig, signature, signature_len))) {
a2bb4cdf
         cli_dbgmsg("crtmgr_verify_pkcs7: mp_read_unsigned_bin failed with %d\n", ret);
50873c8a
         return NULL;
29fb5f5c
     }
 
72fd33c8
     for (i = m->crts; i; i = i->next) {
         if (vrfytype == VRFY_CODE && !i->codeSign)
50873c8a
             continue;
72fd33c8
         if (vrfytype == VRFY_TIME && !i->timeSign)
50873c8a
             continue;
72fd33c8
         if (!memcmp(i->issuer, issuer, sizeof(i->issuer)) &&
             !memcmp(i->serial, serial, sizeof(i->serial))) {
             if (!crtmgr_rsa_verify(i, &sig, hashtype, refhash)) {
a2bb4cdf
                 break;
             }
             cli_dbgmsg("crtmgr_verify_pkcs7: found cert with matching issuer and serial but RSA verification failed\n");
278b2b28
         }
29fb5f5c
     }
     mp_clear(&sig);
f5092717
     return i;
29fb5f5c
 }
71da61a7
 
3cf1b1c5
 int crtmgr_add_roots(struct cl_engine *engine, crtmgr *m, int exclude_bl_crts)
72fd33c8
 {
cd94be7a
     cli_crt *crt;
56b4f4b0
     /*
d12f1646
      * Certs are cached in engine->cmgr. Copy from there.
56b4f4b0
      */
d12f1646
     if (m != &(engine->cmgr)) {
72fd33c8
         for (crt = engine->cmgr.crts; crt != NULL; crt = crt->next) {
3cf1b1c5
             if (exclude_bl_crts && crt->isBlacklisted) {
                 continue;
             }
72fd33c8
             if (crtmgr_add(m, crt)) {
                 crtmgr_free(m);
                 return 1;
             }
         }
 
         return 0;
56b4f4b0
     }
7bcfb2f3
 
d12f1646
     return 0;
71da61a7
 }