/** * gnutls_x509_trust_list_add_crls: * @list: The structure of the list * @crl_list: A list of CRLs * @crl_size: The length of the CRL list * @flags: if GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added. * @verification_flags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL * * This function will add the given certificate revocation lists * to the trusted list. The list of CRLs must not be deinitialized * during this structure's lifetime. * * This function must be called after gnutls_x509_trust_list_add_cas() * to allow verifying the CRLs for validity. * * Returns: The number of added elements is returned. * * Since: 3.0.0 **/ int gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list, const gnutls_x509_crl_t * crl_list, int crl_size, unsigned int flags, unsigned int verification_flags) { int ret, i, j = 0; gnutls_datum_t dn; unsigned int vret = 0; uint32_t hash; /* Probably we can optimize things such as removing duplicates * etc. */ if (crl_size == 0 || crl_list == NULL) return 0; for (i = 0; i < crl_size; i++) { ret = gnutls_x509_crl_get_raw_issuer_dn(crl_list[i], &dn); if (ret < 0) { gnutls_assert(); return i; } hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH); hash %= list->size; _gnutls_free_datum(&dn); if (flags & GNUTLS_TL_VERIFY_CRL) { ret = gnutls_x509_crl_verify(crl_list[i], list->node[hash].trusted_cas, list->node[hash].trusted_ca_size, verification_flags, &vret); if (ret < 0 || vret != 0) continue; } list->node[hash].crls = gnutls_realloc_fast(list->node[hash].crls, (list->node[hash].crl_size + 1) * sizeof(list->node[hash].trusted_cas[0])); if (list->node[hash].crls == NULL) { gnutls_assert(); return i; } list->node[hash].crls[list->node[hash].crl_size] = crl_list[i]; list->node[hash].crl_size++; j++; } return j; }
void doit(void) { int exit_val = 0; size_t i; int ret; gnutls_x509_trust_list_t tl; unsigned int verify_status; gnutls_x509_crl_t crl; gnutls_x509_crt_t ca; gnutls_datum_t tmp; /* The overloading of time() seems to work in linux (ELF?) * systems only. Disable it on windows. */ #ifdef _WIN32 exit(77); #endif ret = global_init(); if (ret != 0) { fail("%d: %s\n", ret, gnutls_strerror(ret)); exit(1); } gnutls_global_set_time_function(mytime); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(4711); for (i = 0; crl_list[i].name; i++) { if (debug) printf("Chain '%s' (%d)...\n", crl_list[i].name, (int) i); if (debug > 2) printf("\tAdding CRL..."); ret = gnutls_x509_crl_init(&crl); if (ret < 0) { fprintf(stderr, "gnutls_x509_crl_init[%d]: %s\n", (int) i, gnutls_strerror(ret)); exit(1); } tmp.data = (unsigned char *) *crl_list[i].crl; tmp.size = strlen(*crl_list[i].crl); ret = gnutls_x509_crl_import(crl, &tmp, GNUTLS_X509_FMT_PEM); if (debug > 2) printf("done\n"); if (ret < 0) { fprintf(stderr, "gnutls_x509_crl_import[%s]: %s\n", crl_list[i].name, gnutls_strerror(ret)); exit(1); } gnutls_x509_crl_print(crl, GNUTLS_CRT_PRINT_ONELINE, &tmp); if (debug) printf("\tCRL: %.*s\n", tmp.size, tmp.data); gnutls_free(tmp.data); if (debug > 2) printf("\tAdding CA certificate..."); ret = gnutls_x509_crt_init(&ca); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_init: %s\n", gnutls_strerror(ret)); exit(1); } tmp.data = (unsigned char *) *crl_list[i].ca; tmp.size = strlen(*crl_list[i].ca); ret = gnutls_x509_crt_import(ca, &tmp, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_import: %s\n", gnutls_strerror(ret)); exit(1); } if (debug > 2) printf("done\n"); gnutls_x509_crt_print(ca, GNUTLS_CRT_PRINT_ONELINE, &tmp); if (debug) printf("\tCA Certificate: %.*s\n", tmp.size, tmp.data); gnutls_free(tmp.data); if (debug) printf("\tVerifying..."); ret = gnutls_x509_crl_verify(crl, &ca, 1, crl_list[i].verify_flags, &verify_status); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_list_verify[%d]: %s\n", (int) i, gnutls_strerror(ret)); exit(1); } if (verify_status != crl_list[i].expected_verify_result) { gnutls_datum_t out1, out2; gnutls_certificate_verification_status_print (verify_status, GNUTLS_CRT_X509, &out1, 0); gnutls_certificate_verification_status_print(crl_list [i]. expected_verify_result, GNUTLS_CRT_X509, &out2, 0); fail("chain[%s]:\nverify_status: %d: %s\nexpected: %d: %s\n", crl_list[i].name, verify_status, out1.data, crl_list[i].expected_verify_result, out2.data); gnutls_free(out1.data); gnutls_free(out2.data); if (!debug) exit(1); } else if (debug) printf("done\n"); gnutls_x509_trust_list_init(&tl, 0); ret = gnutls_x509_trust_list_add_cas(tl, &ca, 1, 0); if (ret != 1) { fail("gnutls_x509_trust_list_add_trust_mem\n"); exit(1); } /* make sure that the two functions don't diverge */ ret = gnutls_x509_trust_list_add_crls(tl, &crl, 1, GNUTLS_TL_VERIFY_CRL, crl_list[i].verify_flags); if (crl_list[i].expected_verify_result == 0 && ret < 0) { fprintf(stderr, "gnutls_x509_trust_list_add_crls[%d]: %s\n", (int) i, gnutls_strerror(ret)); exit(1); } if (crl_list[i].expected_verify_result != 0 && ret > 0) { fprintf(stderr, "gnutls_x509_trust_list_add_crls[%d]: succeeded when it shouldn't\n", (int) i); exit(1); } if (debug) printf("\tCleanup..."); gnutls_x509_trust_list_deinit(tl, 0); gnutls_x509_crt_deinit(ca); gnutls_x509_crl_deinit(crl); if (debug) printf("done\n\n\n"); } gnutls_global_deinit(); if (debug) printf("Exit status...%d\n", exit_val); exit(exit_val); }
/** * gnutls_x509_trust_list_add_crls: * @list: The list * @crl_list: A list of CRLs * @crl_size: The length of the CRL list * @flags: flags from %gnutls_trust_list_flags_t * @verification_flags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL * * This function will add the given certificate revocation lists * to the trusted list. The CRLs in @crl_list must not be deinitialized * during the lifetime of @list. * * This function must be called after gnutls_x509_trust_list_add_cas() * to allow verifying the CRLs for validity. If the flag %GNUTLS_TL_NO_DUPLICATES * is given, then the final CRL list will not contain duplicate entries. * * If the flag %GNUTLS_TL_NO_DUPLICATES is given, gnutls_x509_trust_list_deinit() must be * called with parameter @all being 1. * * If flag %GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added, * and if verification fails, they will be skipped. * * Returns: The number of added elements is returned; that includes * duplicate entries. * * Since: 3.0 **/ int gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list, const gnutls_x509_crl_t * crl_list, unsigned crl_size, unsigned int flags, unsigned int verification_flags) { int ret; unsigned x, i, j = 0; unsigned int vret = 0; uint32_t hash; gnutls_x509_crl_t *tmp; /* Probably we can optimize things such as removing duplicates * etc. */ if (crl_size == 0 || crl_list == NULL) return 0; for (i = 0; i < crl_size; i++) { hash = hash_pjw_bare(crl_list[i]->raw_issuer_dn.data, crl_list[i]->raw_issuer_dn.size); hash %= list->size; if (flags & GNUTLS_TL_VERIFY_CRL) { ret = gnutls_x509_crl_verify(crl_list[i], list->node[hash]. trusted_cas, list->node[hash]. trusted_ca_size, verification_flags, &vret); if (ret < 0 || vret != 0) { _gnutls_debug_log("CRL verification failed, not adding it\n"); if (flags & GNUTLS_TL_NO_DUPLICATES) gnutls_x509_crl_deinit(crl_list[i]); if (flags & GNUTLS_TL_FAIL_ON_INVALID_CRL) return gnutls_assert_val(GNUTLS_E_CRL_VERIFICATION_ERROR); continue; } } /* If the CRL added overrides a previous one, then overwrite * the old one */ if (flags & GNUTLS_TL_NO_DUPLICATES) { for (x=0;x<list->node[hash].crl_size;x++) { if (crl_list[i]->raw_issuer_dn.size == list->node[hash].crls[x]->raw_issuer_dn.size && memcmp(crl_list[i]->raw_issuer_dn.data, list->node[hash].crls[x]->raw_issuer_dn.data, crl_list[i]->raw_issuer_dn.size) == 0) { if (gnutls_x509_crl_get_this_update(crl_list[i]) >= gnutls_x509_crl_get_this_update(list->node[hash].crls[x])) { gnutls_x509_crl_deinit(list->node[hash].crls[x]); list->node[hash].crls[x] = crl_list[i]; goto next; } else { /* The new is older, discard it */ gnutls_x509_crl_deinit(crl_list[i]); goto next; } } } } tmp = gnutls_realloc(list->node[hash].crls, (list->node[hash].crl_size + 1) * sizeof(list->node[hash]. crls[0])); if (tmp == NULL) { ret = i; gnutls_assert(); if (flags & GNUTLS_TL_NO_DUPLICATES) while (i < crl_size) gnutls_x509_crl_deinit(crl_list[i++]); return ret; } list->node[hash].crls = tmp; list->node[hash].crls[list->node[hash].crl_size] = crl_list[i]; list->node[hash].crl_size++; next: j++; } return j; }