Ejemplo n.º 1
0
void crtmgr_del(crtmgr *m, cli_crt *x509) {
    cli_crt *i;
    for(i = m->crts; i; i = i->next) {
	if(i==x509) {
	    if(i->prev)
		i->prev->next = i->next;
	    else
		m->crts = i->next;
	    if(i->next)
		i->next->prev = i->prev;
	    cli_crt_clear(x509);
	    free(x509);
	    m->items--;
	    return;
	}
    }
}
Ejemplo n.º 2
0
static int asn1_get_x509(fmap_t *map, const void **asn1data, unsigned int *size, crtmgr *master, crtmgr *other) {
    struct cli_asn1 crt, tbs, obj;
    unsigned int avail, tbssize, issuersize;
    cli_crt_hashtype hashtype1, hashtype2;
    cli_crt x509;
    const uint8_t *tbsdata;
    const void *next, *issuer;

    if(cli_crt_init(&x509))
	return 1;

    do {
	if(asn1_expect_objtype(map, *asn1data, size, &crt, 0x30)) /* SEQUENCE */
	    break;
	*asn1data = crt.next;

	tbsdata = crt.content;
	if(asn1_expect_objtype(map, crt.content, &crt.size, &tbs, 0x30)) /* SEQUENCE - TBSCertificate */
	    break;
	tbssize = (uint8_t *)tbs.next - tbsdata;

	if(asn1_expect_objtype(map, tbs.content, &tbs.size, &obj, 0xa0)) /* [0] */
	    break;
	avail = obj.size;
	next = obj.next;
	if(asn1_expect_obj(map, &obj.content, &avail, 0x02, 1, "\x02")) /* version 3 only */
	    break;
	if(avail) {
	    cli_dbgmsg("asn1_get_x509: found unexpected extra data in version\n");
	    break;
	}

	if(asn1_expect_objtype(map, next, &tbs.size, &obj, 0x02)) /* serialNumber */
	    break;
	if(map_sha1(map, obj.content, obj.size, x509.serial))
	    break;

	if(asn1_expect_rsa(map, &obj.next, &tbs.size, &hashtype1)) /* algo = sha1WithRSAEncryption | md5WithRSAEncryption */
	    break;

	if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* issuer */
	    break;
	issuer = obj.content;
	issuersize = obj.size;

	if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* validity */
	    break;
	avail = obj.size;
	next = obj.content;

	if(asn1_get_time(map, &next, &avail, &x509.not_before)) /* notBefore */
	    break;
	if(asn1_get_time(map, &next, &avail, &x509.not_after)) /* notAfter */
	    break;
	if(x509.not_before >= x509.not_after) {
	    cli_dbgmsg("asn1_get_x509: bad validity\n");
	    break;
	}
	if(avail) {
	    cli_dbgmsg("asn1_get_x509: found unexpected extra data in validity\n");
	    break;
	}

	if(asn1_expect_objtype(map, obj.next, &tbs.size, &obj, 0x30)) /* subject */
	    break;
	if(map_sha1(map, obj.content, obj.size, x509.subject))
	    break;
	if(asn1_get_rsa_pubkey(map, &obj.next, &tbs.size, &x509))
	    break;

	avail = 0;
	while(tbs.size) {
	    if(asn1_get_obj(map, obj.next, &tbs.size, &obj)) {
		tbs.size = 1;
		break;
	    }
	    if(obj.type <= 0xa0 + avail || obj.type > 0xa3) {
		cli_dbgmsg("asn1_get_x509: found type %02x in extensions, expecting a1, a2 or a3\n", obj.type);
		tbs.size = 1;
		break;
	    }
	    avail = obj.type - 0xa0;
	    if(obj.type == 0xa3) {
		struct cli_asn1 exts;
		int have_ext_key = 0;
		if(asn1_expect_objtype(map, obj.content, &obj.size, &exts, 0x30)) {
		    tbs.size = 1;
		    break;
		}
		if(obj.size) {
		    cli_dbgmsg("asn1_get_x509: found unexpected extra data in extensions\n");
		    break;
		}
		while(exts.size) {
		    struct cli_asn1 ext, id, value;
		    if(asn1_expect_objtype(map, exts.content, &exts.size, &ext, 0x30)) {
			exts.size = 1;
			break;
		    }
		    exts.content = ext.next;
		    if(asn1_expect_objtype(map, ext.content, &ext.size, &id, 0x06)) {
			exts.size = 1;
			break;
		    }
		    if(asn1_get_obj(map, id.next, &ext.size, &value)) {
			exts.size = 1;
			break;
		    }
		    if(value.type == 0x01) {
			/* critical flag */
			if(value.size != 1) {
			    cli_dbgmsg("asn1_get_x509: found boolean with wrong length\n");
			    exts.size = 1;
			    break;
			}
			if(asn1_get_obj(map, value.next, &ext.size, &value)) {
			    exts.size = 1;
			    break;
			}
		    }
		    if(value.type != 0x04) {
			cli_dbgmsg("asn1_get_x509: bad extension value type %u\n", value.type);
			exts.size = 1;
			break;
		    }
		    if(ext.size) {
			cli_dbgmsg("asn1_get_x509: extra data in extension\n");
			exts.size = 1;
			break;
		    }
		    if(id.size != 3)
			continue;

		    if(!fmap_need_ptr_once(map, id.content, 3)) {
			exts.size = 1;
			break;
		    }
		    if(!memcmp("\x55\x1d\x0f", id.content, 3)) {
			/* KeyUsage 2.5.29.15 */
			const uint8_t *keyusage = value.content;
			uint8_t usage;
			if(value.size < 4 || value.size > 5) {
			    cli_dbgmsg("asn1_get_x509: bad KeyUsage\n");
			    exts.size = 1;
			    break;
			}
			if(!fmap_need_ptr_once(map, value.content, value.size)) {
			    exts.size = 1;
			    break;
			}
			if(keyusage[0] != 0x03 || keyusage[1] != value.size - 2 || keyusage[2] > 7) {
			    cli_dbgmsg("asn1_get_x509: bad KeyUsage\n");
			    exts.size = 1;
			    break;
			}
			usage = keyusage[3];
			if(value.size == 4)
			    usage &= ~((1 << keyusage[2])-1);
			x509.certSign = ((usage & 4) != 0);
			continue;
		    }
		    if(!memcmp("\x55\x1d\x25", id.content, 3)) {
			/* ExtKeyUsage 2.5.29.37 */
			struct cli_asn1 keypurp;
			have_ext_key = 1;
			if(asn1_expect_objtype(map, value.content, &value.size, &keypurp, 0x30)) {
			    exts.size = 1;
			    break;
			}
			if(value.size) {
			    cli_dbgmsg("asn1_get_x509: extra data in ExtKeyUsage\n");
			    exts.size = 1;
			    break;
			}
			ext.next = keypurp.content;
			while(keypurp.size) {
			    if(asn1_expect_objtype(map, ext.next, &keypurp.size, &ext, 0x06)) {
				exts.size = 1;
				break;
			    }
			    if(ext.size != 8)
				continue;
			    if(!fmap_need_ptr_once(map, ext.content, 8)) {
				exts.size = 1;
				break;
			    }
			    if(!memcmp("\x2b\x06\x01\x05\x05\x07\x03\x03", ext.content, 8)) /* id_kp_codeSigning */
				x509.codeSign = 1;
			    else if(!memcmp("\x2b\x06\x01\x05\x05\x07\x03\x08", ext.content, 8)) /* id_kp_timeStamping */
				x509.timeSign = 1;
			}
			continue;
		    }
		    if(!memcmp("\x55\x1d\x13", id.content, 3)) {
			/* Basic Constraints 2.5.29.19 */
			struct cli_asn1 constr;
			if(asn1_expect_objtype(map, value.content, &value.size, &constr, 0x30)) {
			    exts.size = 1;
			    break;
			}
			if(!constr.size)
			    x509.certSign = 0;
			else {
			    if(asn1_expect_objtype(map, constr.content, &constr.size, &ext, 0x01)) {
				exts.size = 1;
				break;
			    }
			    if(ext.size != 1) {
				cli_dbgmsg("asn1_get_x509: wrong bool size in basic constraint %u\n", ext.size);
				exts.size = 1;
				break;
			    }
			    if(!fmap_need_ptr_once(map, ext.content, 1)) {
				exts.size = 1;
				break;
			    }
			    x509.certSign = (((uint8_t *)(ext.content))[0] != 0);
			}
		    }
		}
		if(exts.size) {
		    tbs.size = 1;
		    break;
		}
		if(!have_ext_key)
		    x509.codeSign = x509.timeSign = 1;
	    }
	}
	if(tbs.size)
	    break;


	if(crtmgr_lookup(master, &x509) || crtmgr_lookup(other, &x509)) {
	    cli_dbgmsg("asn1_get_x509: certificate already exists\n");
	    cli_crt_clear(&x509);
	    return 0;
	}

	if(map_sha1(map, issuer, issuersize, x509.issuer))
	    break;

	if(asn1_expect_rsa(map, &tbs.next, &crt.size, &hashtype2)) /* signature algo = sha1WithRSAEncryption | md5WithRSAEncryption */
	    break;

	if(hashtype1 != hashtype2) {
	    cli_dbgmsg("asn1_get_x509: found conflicting rsa hash types\n");
	    break;
	}
	x509.hashtype = hashtype1;

	if(asn1_expect_objtype(map, tbs.next, &crt.size, &obj, 0x03)) /* signature */
	    break;
	if(obj.size > 513) {
	    cli_dbgmsg("asn1_get_x509: signature too long\n");
	    break;
	}
	if(!fmap_need_ptr_once(map, obj.content, obj.size)) {
	    cli_dbgmsg("asn1_get_x509: cannot read signature\n");
	    break;
	}
	if(mp_read_unsigned_bin(&x509.sig, obj.content, obj.size)) {
	    cli_dbgmsg("asn1_get_x509: cannot convert signature to big number\n");
	    break;
	}
	if(crt.size) {
	    cli_dbgmsg("asn1_get_x509: found unexpected extra data in signature\n");
	    break;
	}

	if((x509.hashtype == CLI_SHA1RSA && map_sha1(map, tbsdata, tbssize, x509.tbshash)) || (x509.hashtype == CLI_MD5RSA && (map_md5(map, tbsdata, tbssize, x509.tbshash))))
	    break;

	if(crtmgr_add(other, &x509))
	    break;
	cli_crt_clear(&x509);
	return 0;
    } while(0);
    cli_crt_clear(&x509);
    return 1;
}
Ejemplo n.º 3
0
int crtmgr_add(crtmgr *m, cli_crt *x509) {
    cli_crt *i;
    int ret = 0;

    for(i = m->crts; i; i = i->next) {
	if(!memcmp(x509->subject, i->subject, sizeof(i->subject)) &&
	   !memcmp(x509->serial, i->subject, sizeof(i->serial)) &&
	   !mp_cmp(&x509->n, &i->n) &&
	   !mp_cmp(&x509->e, &i->e)) {
	    if(x509->not_before >= i->not_before && x509->not_after <= i->not_after) {
		/* Already same or broader */
		ret = 1;
	    }
	    if(i->not_before > x509->not_before && i->not_before <= x509->not_after) {
		/* Extend left */
		i->not_before = x509->not_before;
		ret = 1;
	    }
	    if(i->not_after >= x509->not_before && i->not_after < x509->not_after) {
		/* Extend right */
		i->not_after = x509->not_after;
		ret = 1;
	    }
	    if(!ret)
		continue;
	    i->certSign |= x509->certSign;
	    i->codeSign |= x509->codeSign;
	    i->timeSign |= x509->timeSign;

	    return 0;
	}

    /* If certs match, we're likely just revoking it */
    if (!memcmp(x509->subject, i->subject, sizeof(x509->subject)) &&
        !memcmp(x509->issuer, i->issuer, sizeof(x509->issuer)) &&
        !memcmp(x509->serial, i->serial, sizeof(x509->serial)) &&
        !mp_cmp(&x509->n, &i->n) &&
        !mp_cmp(&x509->e, &i->e)) {
            if (i->isBlacklisted != x509->isBlacklisted)
                i->isBlacklisted = x509->isBlacklisted;

            return 0;
    }
    }

    i = cli_malloc(sizeof(*i));
    if(!i)
	return 1;

    if((ret = mp_init_multi(&i->n, &i->e, &i->sig, NULL))) {
	cli_warnmsg("crtmgr_add: failed to mp_init failed with %d\n", ret);
	free(i);
	return 1;
    }
    if((ret = mp_copy(&x509->n, &i->n)) || (ret = mp_copy(&x509->e, &i->e)) || (ret = mp_copy(&x509->sig, &i->sig))) {
	cli_warnmsg("crtmgr_add: failed to mp_init failed with %d\n", ret);
	cli_crt_clear(i);
	free(i);
	return 1;
    }
    memcpy(i->subject, x509->subject, sizeof(i->subject));
    memcpy(i->serial, x509->serial, sizeof(i->serial));
    memcpy(i->issuer, x509->issuer, sizeof(i->issuer));
    memcpy(i->tbshash, x509->tbshash, sizeof(i->tbshash));
    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;
    i->isBlacklisted = x509->isBlacklisted;
    i->next = m->crts;
    i->prev = NULL;
    if(m->crts)
	m->crts->prev = i;
    m->crts = i;

    if(cli_debug_flag) {
        char issuer[SHA1_HASH_SIZE*2+1], subject[SHA1_HASH_SIZE*2+1];
        char mod[1024], exp[1024];
        int j=1024;
        // mod first
        fp_toradix_n(&i->n, mod, 16, j);
        // exp next
        fp_toradix_n(&i->e, exp, 16, j);
        // subject and issuer hashes
        for(j=0; j<SHA1_HASH_SIZE; j++) {
            sprintf(&issuer[j*2], "%02x", i->issuer[j]);
            sprintf(&subject[j*2], "%02x", i->subject[j]);
        }
        // printing lines, broken up to minimize truncation
        cli_dbgmsg("crtmgr_add: added cert s:%s i:%s %lu->%lu %s%s%s\n", subject, issuer, (unsigned long)i->not_before, (unsigned long)i->not_after, i->certSign ? "cert ":"", i->codeSign ? "code ":"", i->timeSign ? "time":"");
        cli_dbgmsg("crtmgr_add: n:%s \n", mod);
        cli_dbgmsg("crtmgr_add: e:%s \n", exp);
    }
    m->items++;
    return 0;
}
Ejemplo n.º 4
0
int crtmgr_add(crtmgr *m, cli_crt *x509) {
    cli_crt *i;
    int ret = 0;

    for(i = m->crts; i; i = i->next) {
	if(!memcmp(x509->subject, i->subject, sizeof(i->subject)) &&
	   !memcmp(x509->serial, i->subject, sizeof(i->serial)) &&
	   !mp_cmp(&x509->n, &i->n) &&
	   !mp_cmp(&x509->e, &i->e)) {
	    if(x509->not_before >= i->not_before && x509->not_after <= i->not_after) {
		/* Already same or broader */
		ret = 1;
	    }
	    if(i->not_before > x509->not_before && i->not_before <= x509->not_after) {
		/* Extend left */
		i->not_before = x509->not_before;
		ret = 1;
	    }
	    if(i->not_after >= x509->not_before && i->not_after < x509->not_after) {
		/* Extend right */
		i->not_after = x509->not_after;
		ret = 1;
	    }
	    if(!ret)
		continue;
	    i->certSign |= x509->certSign;
	    i->codeSign |= x509->codeSign;
	    i->timeSign |= x509->timeSign;

	    return 0;
	}

    /* If certs match, we're likely just revoking it */
    if (!memcmp(x509->subject, i->subject, sizeof(x509->subject)) &&
        !memcmp(x509->issuer, i->issuer, sizeof(x509->issuer)) &&
        !memcmp(x509->serial, i->serial, sizeof(x509->serial)) &&
        !mp_cmp(&x509->n, &i->n) &&
        !mp_cmp(&x509->e, &i->e)) {
            if (i->isBlacklisted != x509->isBlacklisted)
                i->isBlacklisted = x509->isBlacklisted;

            return 0;
    }
    }

    i = cli_malloc(sizeof(*i));
    if(!i)
	return 1;

    if((ret = mp_init_multi(&i->n, &i->e, &i->sig, NULL))) {
	cli_warnmsg("crtmgr_add: failed to mp_init failed with %d\n", ret);
	free(i);
	return 1;
    }
    if((ret = mp_copy(&x509->n, &i->n)) || (ret = mp_copy(&x509->e, &i->e)) || (ret = mp_copy(&x509->sig, &i->sig))) {
	cli_warnmsg("crtmgr_add: failed to mp_init failed with %d\n", ret);
	cli_crt_clear(i);
	free(i);
	return 1;
    }

    if ((x509->name))
        i->name = strdup(x509->name);
    else
        i->name = NULL;

    memcpy(i->subject, x509->subject, sizeof(i->subject));
    memcpy(i->serial, x509->serial, sizeof(i->serial));
    memcpy(i->issuer, x509->issuer, sizeof(i->issuer));
    memcpy(i->tbshash, x509->tbshash, sizeof(i->tbshash));
    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;
    i->isBlacklisted = x509->isBlacklisted;
    i->next = m->crts;
    i->prev = NULL;
    if(m->crts)
	m->crts->prev = i;
    m->crts = i;

    m->items++;
    return 0;
}