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