Ejemplo n.º 1
0
static int
compare_subject(hx509_cert c1, hx509_cert c2, int *l)
{
    hx509_name n1, n2;
    int ret;

    ret = hx509_cert_get_subject(c1, &n1);
    if (ret) return 1;
    ret = hx509_cert_get_subject(c2, &n2);
    if (ret) return 1;

    *l = hx509_name_cmp(n1, n2);
    hx509_name_free(&n1);
    hx509_name_free(&n2);

    return 0;
}
Ejemplo n.º 2
0
int
hx509_ca_tbs_set_template(hx509_context context,
			  hx509_ca_tbs tbs,
			  int flags,
			  hx509_cert cert)
{
    int ret;

    if (flags & HX509_CA_TEMPLATE_SUBJECT) {
	if (tbs->subject)
	    hx509_name_free(&tbs->subject);
	ret = hx509_cert_get_subject(cert, &tbs->subject);
	if (ret) {
	    hx509_set_error_string(context, 0, ret,
				   "Failed to get subject from template");
	    return ret;
	}
    }
    if (flags & HX509_CA_TEMPLATE_SERIAL) {
	der_free_heim_integer(&tbs->serial);
	ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
	tbs->flags.serial = !ret;
	if (ret) {
	    hx509_set_error_string(context, 0, ret,
				   "Failed to copy serial number");
	    return ret;
	}
    }
    if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
	tbs->notBefore = hx509_cert_get_notBefore(cert);
    if (flags & HX509_CA_TEMPLATE_NOTAFTER)
	tbs->notAfter = hx509_cert_get_notAfter(cert);
    if (flags & HX509_CA_TEMPLATE_SPKI) {
	free_SubjectPublicKeyInfo(&tbs->spki);
	ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
	tbs->flags.key = !ret;
	if (ret)
	    return ret;
    }
    if (flags & HX509_CA_TEMPLATE_KU) {
	KeyUsage ku;
	ret = _hx509_cert_get_keyusage(context, cert, &ku);
	if (ret)
	    return ret;
	tbs->key_usage = KeyUsage2int(ku);
    }
    if (flags & HX509_CA_TEMPLATE_EKU) {
	ExtKeyUsage eku;
	int i;
	ret = _hx509_cert_get_eku(context, cert, &eku);
	if (ret)
	    return ret;
	for (i = 0; i < eku.len; i++) {
	    ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
	    if (ret) {
		free_ExtKeyUsage(&eku);
		return ret;
	    }
	}
	free_ExtKeyUsage(&eku);
    }
    return 0;
}
Ejemplo n.º 3
0
krb5_error_code
krb5_kdc_pk_initialize(krb5_context context,
		       krb5_kdc_configuration *config,
		       const char *user_id,
		       const char *anchors,
		       char **pool,
		       char **revoke_list)
{
    const char *file;
    char *fn = NULL;
    krb5_error_code ret;

    file = krb5_config_get_string(context, NULL,
				  "libdefaults", "moduli", NULL);

    ret = _krb5_parse_moduli(context, file, &moduli);
    if (ret)
	krb5_err(context, 1, ret, "PKINIT: failed to load modidi file");

    principal_mappings.len = 0;
    principal_mappings.val = NULL;

    ret = _krb5_pk_load_id(context,
			   &kdc_identity,
			   user_id,
			   anchors,
			   pool,
			   revoke_list,
			   NULL,
			   NULL,
			   NULL);
    if (ret) {
	krb5_warn(context, ret, "PKINIT: ");
	config->enable_pkinit = 0;
	return ret;
    }

    {
	hx509_query *q;
	hx509_cert cert;

	ret = hx509_query_alloc(context->hx509ctx, &q);
	if (ret) {
	    krb5_warnx(context, "PKINIT: out of memory");
	    return ENOMEM;
	}

	hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
	if (config->pkinit_kdc_friendly_name)
	    hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name);

	ret = hx509_certs_find(context->hx509ctx,
			       kdc_identity->certs,
			       q,
			       &cert);
	hx509_query_free(context->hx509ctx, q);
	if (ret == 0) {
	    if (hx509_cert_check_eku(context->hx509ctx, cert,
				     &asn1_oid_id_pkkdcekuoid, 0)) {
		hx509_name name;
		char *str;
		ret = hx509_cert_get_subject(cert, &name);
		if (ret == 0) {
		    hx509_name_to_string(name, &str);
		    krb5_warnx(context, "WARNING Found KDC certificate (%s)"
			       "is missing the PK-INIT KDC EKU, this is bad for "
			       "interoperability.", str);
		    hx509_name_free(&name);
		    free(str);
		}
	    }
	    hx509_cert_free(cert);
	} else
	    krb5_warnx(context, "PKINIT: failed to find a signing "
		       "certifiate with a public key");
    }

    if (krb5_config_get_bool_default(context,
				     NULL,
				     FALSE,
				     "kdc",
				     "pkinit_allow_proxy_certificate",
				     NULL))
	config->pkinit_allow_proxy_certs = 1;

    file = krb5_config_get_string(context,
				  NULL,
				  "kdc",
				  "pkinit_mappings_file",
				  NULL);
    if (file == NULL) {
	int aret;

	aret = asprintf(&fn, "%s/pki-mapping", hdb_db_dir(context));
	if (aret == -1) {
	    krb5_warnx(context, "PKINIT: out of memory");
	    return ENOMEM;
	}

	file = fn;
    }

    load_mappings(context, file);
    if (fn)
	free(fn);

    return 0;
}
Ejemplo n.º 4
0
static int HX509_LIB_CALL
add_cert(hx509_context hxctx, void *ctx, hx509_cert cert)
{
    static char empty[] = "";
    struct foo *foo = (struct foo *)ctx;
    struct st_object *o = NULL;
    CK_OBJECT_CLASS type;
    CK_BBOOL bool_true = CK_TRUE;
    CK_BBOOL bool_false = CK_FALSE;
    CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
    CK_KEY_TYPE key_type;
    CK_MECHANISM_TYPE mech_type;
    CK_RV ret = CKR_GENERAL_ERROR;
    int hret;
    heim_octet_string cert_data, subject_data, issuer_data, serial_data;

    st_logf("adding certificate\n");

    serial_data.data = NULL;
    serial_data.length = 0;
    cert_data = subject_data = issuer_data = serial_data;

    hret = hx509_cert_binary(hxctx, cert, &cert_data);
    if (hret)
	goto out;

    {
	    hx509_name name;

	    hret = hx509_cert_get_issuer(cert, &name);
	    if (hret)
		goto out;
	    hret = hx509_name_binary(name, &issuer_data);
	    hx509_name_free(&name);
	    if (hret)
		goto out;

	    hret = hx509_cert_get_subject(cert, &name);
	    if (hret)
		goto out;
	    hret = hx509_name_binary(name, &subject_data);
	    hx509_name_free(&name);
	    if (hret)
		goto out;
    }

    {
	AlgorithmIdentifier alg;

	hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg);
	if (hret) {
	    ret = CKR_DEVICE_MEMORY;
	    goto out;
	}

	key_type = CKK_RSA; /* XXX */

	free_AlgorithmIdentifier(&alg);
    }


    type = CKO_CERTIFICATE;
    o = add_st_object();
    if (o == NULL) {
	ret = CKR_DEVICE_MEMORY;
	goto out;
    }

    o->cert = hx509_cert_ref(cert);

    add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));

    add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
    add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));

    add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
    add_object_attribute(o, 0, CKA_ISSUER, issuer_data.data, issuer_data.length);
    add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data.data, serial_data.length);
    add_object_attribute(o, 0, CKA_VALUE, cert_data.data, cert_data.length);
    add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));

    st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));

    type = CKO_PUBLIC_KEY;
    o = add_st_object();
    if (o == NULL) {
	ret = CKR_DEVICE_MEMORY;
	goto out;
    }
    o->cert = hx509_cert_ref(cert);

    add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));

    add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
    add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
    add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
    add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
    add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
    mech_type = CKM_RSA_X_509;
    add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));

    add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
    add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));

    add_pubkey_info(hxctx, o, key_type, cert);

    st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));

    if (hx509_cert_have_private_key(cert)) {
	CK_FLAGS flags;

	type = CKO_PRIVATE_KEY;

        /* Note to static analyzers: `o' is still referred to via globals */
	o = add_st_object();
	if (o == NULL) {
	    ret = CKR_DEVICE_MEMORY;
	    goto out;
	}
	o->cert = hx509_cert_ref(cert);

	add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
	add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));

	add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
	add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
	add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
	add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
	add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
	mech_type = CKM_RSA_X_509;
	add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));

	add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
	add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
	flags = 0;
	add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));

	add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));

	add_pubkey_info(hxctx, o, key_type, cert);
    }

    ret = CKR_OK;
 out:
    if (ret != CKR_OK) {
	st_logf("something went wrong when adding cert!\n");

	/* XXX wack o */;
    }
    hx509_xfree(cert_data.data);
    hx509_xfree(serial_data.data);
    hx509_xfree(issuer_data.data);
    hx509_xfree(subject_data.data);

    /* Note to static analyzers: `o' is still referred to via globals */
    return 0;
}
Ejemplo n.º 5
0
int
hx509_validate_cert(hx509_context context,
		    hx509_validate_ctx ctx,
		    hx509_cert cert)
{
    Certificate *c = _hx509_get_cert(cert);
    TBSCertificate *t = &c->tbsCertificate;
    hx509_name issuer, subject;
    char *str;
    struct cert_status status;
    int ret;

    memset(&status, 0, sizeof(status));

    if (_hx509_cert_get_version(c) != 3)
	validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
		       "Not version 3 certificate\n");

    if ((t->version == NULL || *t->version < 2) && t->extensions)
	validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
		       "Not version 3 certificate with extensions\n");
	
    if (_hx509_cert_get_version(c) >= 3 && t->extensions == NULL)
	validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
		       "Version 3 certificate without extensions\n");

    ret = hx509_cert_get_subject(cert, &subject);
    if (ret) abort();
    hx509_name_to_string(subject, &str);
    validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
		   "subject name: %s\n", str);
    free(str);

    ret = hx509_cert_get_issuer(cert, &issuer);
    if (ret) abort();
    hx509_name_to_string(issuer, &str);
    validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
		   "issuer name: %s\n", str);
    free(str);

    if (hx509_name_cmp(subject, issuer) == 0) {
	status.selfsigned = 1;
	validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
		       "\tis a self-signed certificate\n");
    }

    validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
		   "Validity:\n");

    Time2string(&t->validity.notBefore, &str);
    validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tnotBefore %s\n", str);
    free(str);
    Time2string(&t->validity.notAfter, &str);
    validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "\tnotAfter  %s\n", str);
    free(str);

    if (t->extensions) {
	int i, j;

	if (t->extensions->len == 0) {
	    validate_print(ctx,
			   HX509_VALIDATE_F_VALIDATE|HX509_VALIDATE_F_VERBOSE,
			   "The empty extensions list is not "
			   "allowed by PKIX\n");
	}

	for (i = 0; i < t->extensions->len; i++) {

	    for (j = 0; check_extension[j].name; j++)
		if (der_heim_oid_cmp(check_extension[j].oid,
				     &t->extensions->val[i].extnID) == 0)
		    break;
	    if (check_extension[j].name == NULL) {
		int flags = HX509_VALIDATE_F_VERBOSE;
		if (t->extensions->val[i].critical)
		    flags |= HX509_VALIDATE_F_VALIDATE;
		validate_print(ctx, flags, "don't know what ");
		if (t->extensions->val[i].critical)
		    validate_print(ctx, flags, "and is CRITICAL ");
		if (ctx->flags & flags)
		    hx509_oid_print(&t->extensions->val[i].extnID,
				    validate_vprint, ctx);
		validate_print(ctx, flags, " is\n");
		continue;
	    }
	    validate_print(ctx,
			   HX509_VALIDATE_F_VALIDATE|HX509_VALIDATE_F_VERBOSE,
			   "checking extention: %s\n",
			   check_extension[j].name);
	    (*check_extension[j].func)(ctx,
				       &status,
				       check_extension[j].cf,
				       &t->extensions->val[i]);
	}
    } else
	validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "no extentions\n");
	
    if (status.isca) {
	if (!status.haveSKI)
	    validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
			   "CA certificate have no SubjectKeyIdentifier\n");

    } else {
	if (!status.haveAKI)
	    validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
			   "Is not CA and doesn't have "
			   "AuthorityKeyIdentifier\n");
    }
	

    if (!status.haveSKI)
	validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
		       "Doesn't have SubjectKeyIdentifier\n");

    if (status.isproxy && status.isca)
	validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
		       "Proxy and CA at the same time!\n");

    if (status.isproxy) {
	if (status.haveSAN)
	    validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
			   "Proxy and have SAN\n");
	if (status.haveIAN)
	    validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
			   "Proxy and have IAN\n");
    }

    if (hx509_name_is_null_p(subject) && !status.haveSAN)
	validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
		       "NULL subject DN and doesn't have a SAN\n");

    if (!status.selfsigned && !status.haveCRLDP)
	validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
		       "Not a CA nor PROXY and doesn't have"
		       "CRL Dist Point\n");

    if (status.selfsigned) {
	ret = _hx509_verify_signature_bitstring(context,
						cert,
						&c->signatureAlgorithm,
						&c->tbsCertificate._save,
						&c->signatureValue);
	if (ret == 0)
	    validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
			   "Self-signed certificate was self-signed\n");
	else
	    validate_print(ctx, HX509_VALIDATE_F_VALIDATE,
			   "Self-signed certificate NOT really self-signed!\n");
    }

    hx509_name_free(&subject);
    hx509_name_free(&issuer);

    return 0;
}
Ejemplo n.º 6
0
int
hx509_ocsp_verify(hx509_context context,
		  time_t now,
		  hx509_cert cert,
		  int flags,
		  const void *data, size_t length,
		  time_t *expiration)
{
    const Certificate *c = _hx509_get_cert(cert);
    OCSPBasicOCSPResponse basic;
    int ret;
    size_t i;

    if (now == 0)
	now = time(NULL);

    *expiration = 0;

    ret = parse_ocsp_basic(data, length, &basic);
    if (ret) {
	hx509_set_error_string(context, 0, ret,
			       "Failed to parse OCSP response");
	return ret;
    }

    for (i = 0; i < basic.tbsResponseData.responses.len; i++) {

	ret = der_heim_integer_cmp(&basic.tbsResponseData.responses.val[i].certID.serialNumber,
			       &c->tbsCertificate.serialNumber);
	if (ret != 0)
	    continue;

	/* verify issuer hashes hash */
	ret = _hx509_verify_signature(context,
				      NULL,
				      &basic.tbsResponseData.responses.val[i].certID.hashAlgorithm,
				      &c->tbsCertificate.issuer._save,
				      &basic.tbsResponseData.responses.val[i].certID.issuerNameHash);
	if (ret != 0)
	    continue;

	switch (basic.tbsResponseData.responses.val[i].certStatus.element) {
	case choice_OCSPCertStatus_good:
	    break;
	case choice_OCSPCertStatus_revoked:
	case choice_OCSPCertStatus_unknown:
	    continue;
	}

	/* don't allow the update to be in the future */
	if (basic.tbsResponseData.responses.val[i].thisUpdate >
	    now + context->ocsp_time_diff)
	    continue;

	/* don't allow the next update to be in the past */
	if (basic.tbsResponseData.responses.val[i].nextUpdate) {
	    if (*basic.tbsResponseData.responses.val[i].nextUpdate < now)
		continue;
	    *expiration = *basic.tbsResponseData.responses.val[i].nextUpdate;
	} else
	    *expiration = now;

	free_OCSPBasicOCSPResponse(&basic);
	return 0;
    }

    free_OCSPBasicOCSPResponse(&basic);

    {
	hx509_name name;
	char *subject;

	ret = hx509_cert_get_subject(cert, &name);
	if (ret) {
	    hx509_clear_error_string(context);
	    goto out;
	}
	ret = hx509_name_to_string(name, &subject);
	hx509_name_free(&name);
	if (ret) {
	    hx509_clear_error_string(context);
	    goto out;
	}
	hx509_set_error_string(context, 0, HX509_CERT_NOT_IN_OCSP,
			       "Certificate %s not in OCSP response "
			       "or not good",
			       subject);
	free(subject);
    }
out:
    return HX509_CERT_NOT_IN_OCSP;
}