verify pkcs#7

remotes/push_mirror/guardrails
aCaB 14 years ago
parent 7bcfb2f3bf
commit 29fb5f5ce9
  1. 137
      libclamav/asn1.c
  2. 281
      libclamav/crtmgr.c
  3. 4
      libclamav/crtmgr.h

@ -566,7 +566,9 @@ int asn1_get_x509(fmap_t *map, void **asn1data, unsigned int *size, crtmgr *mast
int asn1_parse_mscat(FILE *f, crtmgr *cmgr) {
struct cli_asn1 asn1, deep, deeper;
unsigned int size, dsize;
uint8_t sha1[SHA1_HASH_SIZE], issuer[SHA1_HASH_SIZE], md[SHA1_HASH_SIZE], *message, *attrs;
unsigned int size, dsize, message_size, attrs_size;
int got_digest = 0;
fmap_t *map;
void *next;
@ -580,6 +582,7 @@ int asn1_parse_mscat(FILE *f, crtmgr *cmgr) {
break;
}
size = map->len;
if(asn1_expect_objtype(map, next, &size, &asn1, 0x30)) /* SEQUENCE */
break;
if(size) {
@ -636,6 +639,9 @@ int asn1_parse_mscat(FILE *f, crtmgr *cmgr) {
break;
}
message = deep.content;
message_size = deep.size;
dsize = deep.size;
if(asn1_expect_objtype(map, deep.content, &dsize, &deep, 0x30))
break;
@ -677,7 +683,6 @@ int asn1_parse_mscat(FILE *f, crtmgr *cmgr) {
/* FIXME this should be delayed till after the cert is verified */
struct cli_asn1 tagval;
unsigned int tsize, tsize2, hashtype;
uint8_t sha1[SHA1_HASH_SIZE];
void *tagc;
int i;
@ -744,7 +749,7 @@ int asn1_parse_mscat(FILE *f, crtmgr *cmgr) {
cli_crt *x509 = newcerts.crts;
cli_dbgmsg("------------------------\n");
while(x509) {
if(!crtmgr_verify(cmgr, x509)) {
if(!crtmgr_verify_crt(cmgr, x509)) {
if(crtmgr_add(cmgr, x509)) {
/* FIXME handle error */
}
@ -791,20 +796,8 @@ int asn1_parse_mscat(FILE *f, crtmgr *cmgr) {
dsize = asn1.size;
if(asn1_expect_objtype(map, asn1.content, &dsize, &deep, 0x30)) /* issuer */
break;
if(0){
SHA1Context foo;
uint8_t hash[SHA1_HASH_SIZE * 2 + 1];
int i;
if(!fmap_need_ptr_once(map, deep.content, deep.size))
return 1;
SHA1Init (&foo);
SHA1Update (&foo, deep.content, deep.size);
SHA1Final (&foo, &hash[SHA1_HASH_SIZE]);
for(i=0; i<SHA1_HASH_SIZE; i++)
sprintf(&hash[i*2],"%02x", hash[SHA1_HASH_SIZE+i]);
cli_errmsg("final:: %s\n", hash);
}
if(map_sha1(map, deep.content, deep.size, issuer))
break;
if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x02)) /* serial */
break;
@ -815,8 +808,90 @@ int asn1_parse_mscat(FILE *f, crtmgr *cmgr) {
if(asn1_expect_algo(map, &asn1.next, &size, 5, "\x2b\x0e\x03\x02\x1a")) /* digestAlgorithm == sha1 */
break;
attrs = asn1.next;
if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa0)) /* authenticatedAttributes */
break;
attrs_size = (uint8_t *)(asn1.next) - attrs;
dsize = asn1.size;
deep.next = asn1.content;
while(dsize) {
struct cli_asn1 cobj;
int content;
if(asn1_expect_objtype(map, deep.next, &dsize, &deep, 0x30)) { /* attribute */
dsize = 1;
break;
}
if(asn1_expect_objtype(map, deep.content, &deep.size, &deeper, 0x06)) { /* attribute type */
dsize = 1;
break;
}
if(deeper.size != 9)
continue;
if(!fmap_need_ptr_once(map, deeper.content, deeper.size)) {
cli_dbgmsg("asn1_parse_mscat: failed to read authenticated attribute\n");
dsize = 1;
break;
}
if(!memcmp(deeper.content, "\x2a\x86\x48\x86\xf7\x0d\x01\x09\x03", 9))
content = 0; /* contentType */
else if(!memcmp(deeper.content, "\x2a\x86\x48\x86\xf7\x0d\x01\x09\x04", 9))
content = 1; /* messageDigest */
else
continue;
if(asn1_expect_objtype(map, deeper.next, &deep.size, &deeper, 0x31)) { /* set - contents */
dsize = 1;
break;
}
if(deep.size) {
cli_dbgmsg("asn1_parse_mscat: extra data in authenticated attributes\n");
dsize = 1;
break;
}
if(got_digest & (1<<content)) {
cli_dbgmsg("asn1_parse_mscat: contentType or messageDigest appear twice\n");
dsize = 1;
break;
}
if(content == 0) { /* contentType */
/* FIXME CHECK THE ACTUAL CONTENT TYPE MATCHES */
if(asn1_expect_obj(map, deeper.content, &deeper.size, &cobj, 0x06, 9, "\x2b\x06\x01\x04\x01\x82\x37\x0a\x01")) { /* szOID_CTL - 1.3.6.1.4.1.311.10.1 */
dsize = 1;
break;
}
got_digest |= 1;
} else { /* messageDigest */
if(asn1_expect_objtype(map, deeper.content, &deeper.size, &cobj, 0x04)) {
dsize = 1;
break;
}
if(cobj.size != SHA1_HASH_SIZE) {
cli_dbgmsg("asn1_parse_mscat: messageDigest attribute has got the wrong size (%u)\n", cobj.size);
dsize = 1;
break;
}
if(!fmap_need_ptr_once(map, cobj.content, SHA1_HASH_SIZE)) {
cli_dbgmsg("asn1_parse_mscat: failed to read authenticated attribute\n");
dsize = 1;
break;
}
memcpy(md, cobj.content, SHA1_HASH_SIZE);
got_digest |= 2;
}
if(deeper.size) {
cli_dbgmsg("asn1_parse_mscat: extra data in authenticated attribute\n");
dsize = 1;
break;
}
}
if(dsize)
break;
if(got_digest != 3) {
cli_dbgmsg("asn1_parse_mscat: contentType or messageDigest are missing\n");
break;
}
if(asn1_expect_algo(map, &asn1.next, &size, 9, "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01")) /* digestEncryptionAlgorithm == sha1 */
break;
@ -824,9 +899,37 @@ int asn1_parse_mscat(FILE *f, crtmgr *cmgr) {
if(asn1_expect_objtype(map, asn1.next, &size, &asn1, 0x04)) /* encryptedDigest */
break;
if(map_sha1(map, message, message_size, sha1))
break;
if(memcmp(sha1, md, sizeof(sha1))) {
cli_dbgmsg("asn1_parse_mscat: messageDigest mismatch\n");
break;
}
{
SHA1Context ctx;
if(!fmap_need_ptr_once(map, attrs, attrs_size)) {
cli_dbgmsg("map_sha1: failed to read authenticatedAttributes\n");
return 1;
}
SHA1Init(&ctx);
SHA1Update(&ctx, "\x31", 1);
SHA1Update(&ctx, attrs + 1, attrs_size - 1); /* FIXME UNDERFLOW */
SHA1Final(&ctx, sha1);
}
{
fmap_need_ptr_once(map, asn1.content, asn1.size);
if(!crtmgr_verify_pkcs7(cmgr, issuer, asn1.content, asn1.size, CLI_SHA1RSA, sha1)) {
cli_errmsg("verified!!!\n");
}
}
if(size && asn1_expect_objtype(map, asn1.next, &size, &asn1, 0xa1)) /* unauthenticatedAttributes */
break;
/* FIXME : COUNTERSIG verification and timestampinging */
if(size) {
cli_dbgmsg("asn1_parse_mscat: extra data inside signerInfo\n");
break;

@ -108,93 +108,142 @@ void crtmgr_del(crtmgr *m, cli_crt *x509) {
}
}
int crtmgr_verify(crtmgr *m, cli_crt *x509) {
static int crtmgr_rsa_verify(cli_crt *x509, mp_int *sig, cli_crt_hashtype hashtype, const uint8_t *refhash) {
int keylen = mp_unsigned_bin_size(&x509->n), siglen = mp_unsigned_bin_size(sig);
int ret, j, hashlen;
uint8_t d[513];
cli_crt *i = m->crts;
mp_int x;
int ret, j, ref_siglen = mp_unsigned_bin_size(&x509->sig), hashlen;
if((ret = mp_init(&x))) {
cli_errmsg("crtmgr_verify: mp_init failed with %d\n", ret);
cli_errmsg("crtmgr_rsa_verify: mp_init failed with %d\n", ret);
return 1;
}
for(i = m->crts; i; i = i->next) {
int siglen = mp_unsigned_bin_size(&i->n);
if(!memcmp(x509->issuer, i->subject, sizeof(i->subject)) && MAX(siglen, ref_siglen) - MIN(siglen, ref_siglen) <= 1) {
if((ret = mp_exptmod(&x509->sig, &i->e, &i->n, &x))) {
cli_warnmsg("crtmgr_verify: verification failed: mp_exptmod failed with %d\n", ret);
continue;
}
if(mp_unsigned_bin_size(&x) != siglen - 1)
continue;
if((ret = mp_to_unsigned_bin(&x, d))) {
cli_warnmsg("crtmgr_verify: mp_unsigned_bin_size failed with %d\n", ret);
continue;
do {
if(MAX(keylen, siglen) - MIN(keylen, siglen) > 1)
break;
if((ret = mp_exptmod(sig, &x509->e, &x509->n, &x))) {
cli_warnmsg("crtmgr_rsa_verify: verification failed: mp_exptmod failed with %d\n", ret);
break;
}
if(mp_unsigned_bin_size(&x) != keylen - 1)
break;
if((ret = mp_to_unsigned_bin(&x, d))) {
cli_warnmsg("crtmgr_rsa_verify: mp_unsigned_bin_size failed with %d\n", ret);
break;
}
if(*d != 1) /* block type 1 */
break;
keylen -= 1; /* 0xff padding */
for(j=1; j<keylen-2; j++)
if(d[j] != 0xff)
break;
if(j == keylen - 2)
break;
if(d[j] != 0) /* 0x00 separator */
break;
j++;
keylen -= j; /* asn1 size */
/* SEQ { SEQ { OID, NULL }, OCTET STRING */
if(keylen < 2 || d[j] != 0x30 || d[j+1] + 2 != keylen)
break;
keylen -= 2;
j+=2;
if(keylen <2 || d[j] != 0x30)
break;
hashlen = d[j+1];
keylen -= 2;
j+=2;
if(keylen < hashlen)
break;
if(hashlen == 9) {
if(hashtype != CLI_SHA1RSA || memcmp(&d[j], "\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00", 9)) {
cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
break;
}
if(*d != 1) /* block type 1 */
continue;
siglen -= 1; /* 0xff padding */
for(j=1; j<siglen-2; j++)
if(d[j] != 0xff)
break;
if(j == siglen - 2)
continue;
if(d[j] != 0) /* 0x00 separator */
continue;
j++;
siglen -= j; /* asn1 size */
/* SEQ { SEQ { OID, NULL }, OCTET STRING */
if(siglen < 2 || d[j] != 0x30 || d[j+1] + 2 != siglen)
continue;
siglen -= 2;
j+=2;
if(siglen <2 || d[j] != 0x30)
continue;
hashlen = d[j+1];
siglen -= 2;
j+=2;
if(siglen < hashlen)
continue;
if(hashlen == 9) {
if(x509->hashtype != CLI_SHA1RSA || memcmp(&d[j], "\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00", 9)) {
cli_errmsg("crtmgr_verify: ACAB - CRYPTO MISSING?\n");
continue;
}
} else if(hashlen == 12) {
if(x509->hashtype != CLI_MD5RSA || memcmp(&d[j], "\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00", 12)) {
cli_errmsg("crtmgr_verify: ACAB - CRYPTO MISSING?\n");
continue;
}
} else {
cli_errmsg("crtmgr_verify: ACAB - CRYPTO MISSING?\n");
continue;
} else if(hashlen == 12) {
if(hashtype != CLI_MD5RSA || memcmp(&d[j], "\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00", 12)) {
cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
break;
}
} else {
cli_errmsg("crtmgr_rsa_verify: FIXME ACAB - CRYPTO MISSING?\n");
break;
}
keylen -= hashlen;
j += hashlen;
hashlen = (hashtype == CLI_SHA1RSA) ? SHA1_HASH_SIZE : 16;
if(keylen < 2 || d[j] != 0x04 || d[j+1] != hashlen)
break;
keylen -= 2;
j+=2;
if(keylen != hashlen)
break;
if(memcmp(&d[j], refhash, hashlen))
break;
mp_clear(&x);
return 0;
} while(0);
siglen -= hashlen;
j += hashlen;
hashlen = x509->hashtype == CLI_SHA1RSA ? SHA1_HASH_SIZE : 16;
if(siglen < 2 || d[j] != 0x04 || d[j+1] != hashlen)
continue;
siglen -= 2;
j+=2;
if(siglen != hashlen)
continue;
if(memcmp(&d[j], x509->tbshash, hashlen))
continue;
mp_clear(&x);
mp_clear(&x);
return 1;
}
int crtmgr_verify_crt(crtmgr *m, cli_crt *x509) {
cli_crt *i = m->crts;
for(i = m->crts; i; i = i->next) {
if(!memcmp(i->subject, x509->issuer, sizeof(i->subject)) &&
!crtmgr_rsa_verify(i, &x509->sig, x509->hashtype, x509->tbshash))
return 0;
}
}
mp_clear(&x);
return 1;
}
int crtmgr_verify_pkcs7(crtmgr *m, uint8_t *issuer, void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash) {
cli_crt *i;
mp_int sig;
int ret;
/* FIXME: add check on serial ? */
if(signature_len < 1024/8 || signature_len > 4096/8+1) {
cli_dbgmsg("crtmgr_verify_pkcs7: unsupported sig len: %u\n", signature_len);
return 1;
}
if((ret = mp_init(&sig))) {
cli_errmsg("crtmgr_verify_pkcs7: mp_init failed with %d\n", ret);
return 1;
}
if((ret=mp_read_unsigned_bin(&sig, signature, signature_len))) {
cli_warnmsg("crtmgr_verify_pkcs7: mp_read_unsigned_bin failed with %d\n", ret);
return 1;
}
ret = 1;
for(i = m->crts; i; i = i->next) {
if(!memcmp(i->issuer, issuer, sizeof(i->issuer)) &&
!crtmgr_rsa_verify(i, &sig, hashtype, refhash)) {
ret = 0;
break;
}
}
mp_clear(&sig);
return ret;
}
/* DC=com, DC=microsoft, CN=Microsoft Root Certificate Authority */
const uint8_t MSCA_SUBJECT[] = "\x11\x3b\xd8\x6b\xed\xde\xbc\xd4\xc5\xf1\x0a\xa0\x7a\xb2\x02\x6b\x98\x2f\x4b\x92";
@ -291,80 +340,48 @@ const uint8_t VER_EXP[] = "\x01\x00\x01";
int crtmgr_add_roots(crtmgr *m) {
cli_crt msca;
if(cli_crt_init(&msca))
cli_crt ca;
if(cli_crt_init(&ca))
return 1;
/* FIXME proper error check and error path cleanup */
memset(msca.issuer, '\xca', sizeof(msca.issuer));
memcpy(msca.subject, MSCA_SUBJECT, sizeof(msca.subject));
if(mp_read_unsigned_bin(&msca.n, MSCA_MOD, sizeof(MSCA_MOD)-1) || mp_read_unsigned_bin(&msca.e, MSCA_EXP, sizeof(MSCA_EXP)-1)) {
cli_crt_clear(&msca);
memset(ca.issuer, '\xca', sizeof(ca.issuer));
memcpy(ca.subject, MSCA_SUBJECT, sizeof(ca.subject));
if(mp_read_unsigned_bin(&ca.n, MSCA_MOD, sizeof(MSCA_MOD)-1) || mp_read_unsigned_bin(&ca.e, MSCA_EXP, sizeof(MSCA_EXP)-1)) {
cli_crt_clear(&ca);
return 1;
}
msca.not_before = 989450362; /* May 9 23:19:22 2001 GMT */
msca.not_after = 1620602293; /* May 9 23:28:13 2021 GMT */
crtmgr_add(m, &msca);
ca.not_before = 989450362; /* May 9 23:19:22 2001 GMT */
ca.not_after = 1620602293; /* May 9 23:28:13 2021 GMT */
crtmgr_add(m, &ca);
memcpy(msca.subject, MSA_SUBJECT, sizeof(msca.subject));
if(mp_read_unsigned_bin(&msca.n, MSA_MOD, sizeof(MSA_MOD)-1) || mp_read_unsigned_bin(&msca.e, MSA_EXP, sizeof(MSA_EXP)-1)) {
cli_crt_clear(&msca);
memcpy(ca.subject, MSA_SUBJECT, sizeof(ca.subject));
if(mp_read_unsigned_bin(&ca.n, MSA_MOD, sizeof(MSA_MOD)-1) || mp_read_unsigned_bin(&ca.e, MSA_EXP, sizeof(MSA_EXP)-1)) {
cli_crt_clear(&ca);
return 1;
}
msca.not_before = 852879600; /* Jan 10 07:00:00 1997 GMT */
msca.not_after = 1609398000; /* Dec 31 07:00:00 2020 GMT */
crtmgr_add(m, &msca);
ca.not_before = 852879600; /* Jan 10 07:00:00 1997 GMT */
ca.not_after = 1609398000; /* Dec 31 07:00:00 2020 GMT */
crtmgr_add(m, &ca);
memcpy(msca.subject, THAW_SUBJECT, sizeof(msca.subject));
if(mp_read_unsigned_bin(&msca.n, THAW_MOD, sizeof(THAW_MOD)-1) || mp_read_unsigned_bin(&msca.e, THAW_EXP, sizeof(THAW_EXP)-1)) {
cli_crt_clear(&msca);
memcpy(ca.subject, THAW_SUBJECT, sizeof(ca.subject));
if(mp_read_unsigned_bin(&ca.n, THAW_MOD, sizeof(THAW_MOD)-1) || mp_read_unsigned_bin(&ca.e, THAW_EXP, sizeof(THAW_EXP)-1)) {
cli_crt_clear(&ca);
return 1;
}
msca.not_before = 852076800; /* Jan 01 00:00:00 1997 GMT */
msca.not_after = 1609459199; /* Dec 31 23:59:59 2020 GMT */
crtmgr_add(m, &msca);
ca.not_before = 852076800; /* Jan 01 00:00:00 1997 GMT */
ca.not_after = 1609459199; /* Dec 31 23:59:59 2020 GMT */
crtmgr_add(m, &ca);
memcpy(msca.subject, VER_SUBJECT, sizeof(msca.subject));
if(mp_read_unsigned_bin(&msca.n, VER_MOD, sizeof(VER_MOD)-1) || mp_read_unsigned_bin(&msca.e, VER_EXP, sizeof(VER_EXP)-1)) {
cli_crt_clear(&msca);
memcpy(ca.subject, VER_SUBJECT, sizeof(ca.subject));
if(mp_read_unsigned_bin(&ca.n, VER_MOD, sizeof(VER_MOD)-1) || mp_read_unsigned_bin(&ca.e, VER_EXP, sizeof(VER_EXP)-1)) {
cli_crt_clear(&ca);
return 1;
}
msca.not_before = 822873600; /* Jan 29 00:00:00 1996 GMT */
msca.not_after = 1848787199; /* Aug 1 23:59:59 2028 GMT */
crtmgr_add(m, &msca);
ca.not_before = 822873600; /* Jan 29 00:00:00 1996 GMT */
ca.not_after = 1848787199; /* Aug 1 23:59:59 2028 GMT */
crtmgr_add(m, &ca);
return 0;
}
/* typedef struct { */
/* cli_crt *certs; */
/* unsigned int ncerts; */
/* } *crtmgr; */
/* /\* if(mp_init(&n) || mp_read_signed_bin(&n, obj.content, obj.size)) *\/ */
/* void crt_destroy(cli_crt *crt) { */
/* mp_clear_multi(&crt->n, &crt->e); */
/* free(crt); */
/* } */
/* void crt_set_issuer(cli_crt *crt, const char issuer[SHA1_HASH_SIZE]) { */
/* memcpy(crt->issuer, issuer, sizeof(issuer)); */
/* } */
/* int crt_set_rsa(cli_crt *crt, int exp, void *bn, unsigned int bn_len) { */
/* if(mp_read_signed_bin(exp ? &crt->e : &crt->n, bn, bn_len)) */
/* return 1; */
/* return 0; */
/* } */
/* void crt_set_validity(cli_crt *crt, int before, time_t t) { */
/* if(before) */
/* crt->not_before = t; */
/* else */
/* crt->not_after = t; */
/* } */

@ -35,7 +35,9 @@ void crtmgr_init(crtmgr *m);
int crtmgr_add(crtmgr *m, cli_crt *x509);
cli_crt *crtmgr_lookup(crtmgr *m, cli_crt *x509);
void crtmgr_del(crtmgr *m, cli_crt *x509);
int crtmgr_verify(crtmgr *m, cli_crt *x509);
int crtmgr_verify_crt(crtmgr *m, cli_crt *x509);
int crtmgr_verify_pkcs7(crtmgr *m, uint8_t *issuer, void *signature, unsigned int signature_len, cli_crt_hashtype hashtype, const uint8_t *refhash);
int crtmgr_add_roots(crtmgr *m);
#endif

Loading…
Cancel
Save