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 |
} |