/** * gnutls_x509_trust_list_deinit: * @list: The structure to be deinitialized * @all: if non-(0) it will deinitialize all the certificates and CRLs contained in the structure. * * This function will deinitialize a trust list. * * Since: 3.0.0 **/ void gnutls_x509_trust_list_deinit(gnutls_x509_trust_list_t list, unsigned int all) { int i, j; if (!list) return; for (i = 0; i < list->size; i++) { if (all) for (j = 0; j < list->node[i].trusted_ca_size; j++) { gnutls_x509_crt_deinit(list->node[i].trusted_cas[j]); } gnutls_free(list->node[i].trusted_cas); if (all) for (j = 0; j < list->node[i].crl_size; j++) { gnutls_x509_crl_deinit(list->node[i].crls[j]); } gnutls_free(list->node[i].crls); gnutls_free(list->node[i].named_certs); } gnutls_free(list->node); gnutls_free(list); }
int main(void) { int rc; gnutls_certificate_credentials_t crt; gnutls_datum_t crldatum = { (uint8_t *) crl, strlen(crl) }; gnutls_x509_crl_t crl; rc = global_init(); if (rc) { printf("global_init rc %d: %s\n", rc, gnutls_strerror(rc)); return 1; } rc = gnutls_certificate_allocate_credentials(&crt); if (rc) { printf ("gnutls_certificate_allocate_credentials rc %d: %s\n", rc, gnutls_strerror(rc)); return 1; } rc = gnutls_certificate_set_x509_crl_mem(crt, &crldatum, GNUTLS_X509_FMT_PEM); if (rc != 1) { printf("gnutls_certificate_set_x509_crl_mem num %d\n", rc); return 1; } rc = gnutls_x509_crl_init(&crl); if (rc) { printf("gnutls_x509_crl_init rc %d: %s\n", rc, gnutls_strerror(rc)); return 1; } rc = gnutls_x509_crl_import(crl, &crldatum, GNUTLS_X509_FMT_PEM); if (rc) { printf("gnutls_x509_crl_import rc %d: %s\n", rc, gnutls_strerror(rc)); return 1; } rc = gnutls_certificate_set_x509_crl(crt, &crl, 1); if (rc < 0) { printf("gnutls_certificate_set_x509_crl rc %d: %s\n", rc, gnutls_strerror(rc)); return 1; } gnutls_x509_crl_deinit(crl); gnutls_certificate_free_credentials(crt); gnutls_global_deinit(); return 0; }
/** * gnutls_x509_trust_list_deinit: * @list: The structure to be deinitialized * @all: if non-zero it will deinitialize all the certificates and CRLs contained in the structure. * * This function will deinitialize a trust list. Note that the * @all flag should be typically non-zero unless you have specified * your certificates using gnutls_x509_trust_list_add_cas() and you * want to prevent them from being deinitialized by this function. * * Since: 3.0.0 **/ void gnutls_x509_trust_list_deinit(gnutls_x509_trust_list_t list, unsigned int all) { unsigned int i, j; if (!list) return; for (j = 0; j < list->blacklisted_size; j++) { gnutls_x509_crt_deinit(list->blacklisted[j]); } gnutls_free(list->blacklisted); for (j = 0; j < list->keep_certs_size; j++) { gnutls_x509_crt_deinit(list->keep_certs[j]); } gnutls_free(list->keep_certs); for (i = 0; i < list->size; i++) { if (all) { for (j = 0; j < list->node[i].trusted_ca_size; j++) { gnutls_x509_crt_deinit(list->node[i]. trusted_cas[j]); } } gnutls_free(list->node[i].trusted_cas); if (all) { for (j = 0; j < list->node[i].crl_size; j++) { gnutls_x509_crl_deinit(list->node[i]. crls[j]); } } gnutls_free(list->node[i].crls); if (all) { for (j = 0; j < list->node[i].named_cert_size; j++) { gnutls_x509_crt_deinit(list->node[i]. named_certs[j]. cert); } } gnutls_free(list->node[i].named_certs); } gnutls_free(list->x509_rdn_sequence.data); gnutls_free(list->node); gnutls_free(list->pkcs11_token); gnutls_free(list); }
/** * gnutls_certificate_set_x509_crl: * @res: is a #gnutls_certificate_credentials_t type. * @crl_list: is a list of trusted CRLs. They should have been verified before. * @crl_list_size: holds the size of the crl_list * * This function adds the trusted CRLs in order to verify client or * server certificates. In case of a client this is not required to * be called if the certificates are not verified using * gnutls_certificate_verify_peers2(). This function may be called * multiple times. * * Returns: number of CRLs processed, or a negative error code on error. * * Since: 2.4.0 **/ int gnutls_certificate_set_x509_crl(gnutls_certificate_credentials_t res, gnutls_x509_crl_t * crl_list, int crl_list_size) { int ret, i, j; gnutls_x509_crl_t *new_crl = gnutls_malloc(crl_list_size * sizeof(gnutls_x509_crl_t)); unsigned flags = GNUTLS_TL_USE_IN_TLS; if (res->flags & GNUTLS_CERTIFICATE_VERIFY_CRLS) flags |= GNUTLS_TL_VERIFY_CRL|GNUTLS_TL_FAIL_ON_INVALID_CRL; if (!new_crl) return GNUTLS_E_MEMORY_ERROR; for (i = 0; i < crl_list_size; i++) { ret = gnutls_x509_crl_init(&new_crl[i]); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_crl_cpy(new_crl[i], crl_list[i]); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = gnutls_x509_trust_list_add_crls(res->tlist, new_crl, crl_list_size, flags, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } free(new_crl); return ret; cleanup: for (j = 0; j < i; j++) gnutls_x509_crl_deinit(new_crl[j]); free(new_crl); return ret; }
/** * gnutls_pkcs12_simple_parse: * @p12: A pkcs12 type * @password: optional password used to decrypt the structure, bags and keys. * @key: a structure to store the parsed private key. * @chain: the corresponding to key certificate chain (may be %NULL) * @chain_len: will be updated with the number of additional (may be %NULL) * @extra_certs: optional pointer to receive an array of additional * certificates found in the PKCS12 structure (may be %NULL). * @extra_certs_len: will be updated with the number of additional * certs (may be %NULL). * @crl: an optional structure to store the parsed CRL (may be %NULL). * @flags: should be zero or one of GNUTLS_PKCS12_SP_* * * This function parses a PKCS12 structure in @pkcs12 and extracts the * private key, the corresponding certificate chain, any additional * certificates and a CRL. The structures in @key, @chain @crl, and @extra_certs * must not be initialized. * * The @extra_certs and @extra_certs_len parameters are optional * and both may be set to %NULL. If either is non-%NULL, then both must * be set. The value for @extra_certs is allocated * using gnutls_malloc(). * * Encrypted PKCS12 bags and PKCS8 private keys are supported, but * only with password based security and the same password for all * operations. * * Note that a PKCS12 structure may contain many keys and/or certificates, * and there is no way to identify which key/certificate pair you want. * For this reason this function is useful for PKCS12 files that contain * only one key/certificate pair and/or one CRL. * * If the provided structure has encrypted fields but no password * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED. * * Note that normally the chain constructed does not include self signed * certificates, to comply with TLS' requirements. If, however, the flag * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then * self signed certificates will be included in the chain. * * Prior to using this function the PKCS #12 structure integrity must * be verified using gnutls_pkcs12_verify_mac(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.1.0 **/ int gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12, const char *password, gnutls_x509_privkey_t * key, gnutls_x509_crt_t ** chain, unsigned int *chain_len, gnutls_x509_crt_t ** extra_certs, unsigned int *extra_certs_len, gnutls_x509_crl_t * crl, unsigned int flags) { gnutls_pkcs12_bag_t bag = NULL; gnutls_x509_crt_t *_extra_certs = NULL; unsigned int _extra_certs_len = 0; gnutls_x509_crt_t *_chain = NULL; unsigned int _chain_len = 0; int idx = 0; int ret; size_t cert_id_size = 0; size_t key_id_size = 0; uint8_t cert_id[20]; uint8_t key_id[20]; int privkey_ok = 0; unsigned int i; int elements_in_bag; *key = NULL; if (crl) *crl = NULL; /* find the first private key */ for (;;) { ret = gnutls_pkcs12_bag_init(&bag); if (ret < 0) { bag = NULL; gnutls_assert(); goto done; } ret = gnutls_pkcs12_get_bag(p12, idx, bag); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { gnutls_pkcs12_bag_deinit(bag); bag = NULL; break; } if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_pkcs12_bag_get_type(bag, 0); if (ret < 0) { gnutls_assert(); goto done; } if (ret == GNUTLS_BAG_ENCRYPTED) { if (password == NULL) { ret = gnutls_assert_val (GNUTLS_E_DECRYPTION_FAILED); goto done; } ret = gnutls_pkcs12_bag_decrypt(bag, password); if (ret < 0) { gnutls_assert(); goto done; } } elements_in_bag = gnutls_pkcs12_bag_get_count(bag); if (elements_in_bag < 0) { gnutls_assert(); goto done; } for (i = 0; i < (unsigned)elements_in_bag; i++) { int type; gnutls_datum_t data; type = gnutls_pkcs12_bag_get_type(bag, i); if (type < 0) { gnutls_assert(); goto done; } ret = gnutls_pkcs12_bag_get_data(bag, i, &data); if (ret < 0) { gnutls_assert(); goto done; } switch (type) { case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: if (password == NULL) { ret = gnutls_assert_val (GNUTLS_E_DECRYPTION_FAILED); goto done; } FALLTHROUGH; case GNUTLS_BAG_PKCS8_KEY: if (*key != NULL) { /* too simple to continue */ gnutls_assert(); break; } ret = gnutls_x509_privkey_init(key); if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_x509_privkey_import_pkcs8 (*key, &data, GNUTLS_X509_FMT_DER, password, type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0); if (ret < 0) { gnutls_assert(); goto done; } key_id_size = sizeof(key_id); ret = gnutls_x509_privkey_get_key_id(*key, 0, key_id, &key_id_size); if (ret < 0) { gnutls_assert(); goto done; } privkey_ok = 1; /* break */ break; default: break; } } idx++; gnutls_pkcs12_bag_deinit(bag); bag = NULL; if (privkey_ok != 0) /* private key was found */ break; } if (privkey_ok == 0) { /* no private key */ gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } /* now find the corresponding certificate */ idx = 0; bag = NULL; for (;;) { ret = gnutls_pkcs12_bag_init(&bag); if (ret < 0) { bag = NULL; gnutls_assert(); goto done; } ret = gnutls_pkcs12_get_bag(p12, idx, bag); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { gnutls_pkcs12_bag_deinit(bag); bag = NULL; break; } if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_pkcs12_bag_get_type(bag, 0); if (ret < 0) { gnutls_assert(); goto done; } if (ret == GNUTLS_BAG_ENCRYPTED) { ret = gnutls_pkcs12_bag_decrypt(bag, password); if (ret < 0) { gnutls_assert(); goto done; } } elements_in_bag = gnutls_pkcs12_bag_get_count(bag); if (elements_in_bag < 0) { gnutls_assert(); goto done; } for (i = 0; i < (unsigned)elements_in_bag; i++) { int type; gnutls_datum_t data; gnutls_x509_crt_t this_cert; type = gnutls_pkcs12_bag_get_type(bag, i); if (type < 0) { gnutls_assert(); goto done; } ret = gnutls_pkcs12_bag_get_data(bag, i, &data); if (ret < 0) { gnutls_assert(); goto done; } switch (type) { case GNUTLS_BAG_CERTIFICATE: ret = gnutls_x509_crt_init(&this_cert); if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_x509_crt_import(this_cert, &data, GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert(); gnutls_x509_crt_deinit(this_cert); this_cert = NULL; goto done; } /* check if the key id match */ cert_id_size = sizeof(cert_id); ret = gnutls_x509_crt_get_key_id(this_cert, 0, cert_id, &cert_id_size); if (ret < 0) { gnutls_assert(); gnutls_x509_crt_deinit(this_cert); this_cert = NULL; goto done; } if (memcmp(cert_id, key_id, cert_id_size) != 0) { /* they don't match - skip the certificate */ _extra_certs = gnutls_realloc_fast (_extra_certs, sizeof(_extra_certs [0]) * ++_extra_certs_len); if (!_extra_certs) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto done; } _extra_certs [_extra_certs_len - 1] = this_cert; this_cert = NULL; } else { if (chain && _chain_len == 0) { _chain = gnutls_malloc(sizeof (_chain [0]) * (++_chain_len)); if (!_chain) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto done; } _chain[_chain_len - 1] = this_cert; this_cert = NULL; } else { gnutls_x509_crt_deinit (this_cert); this_cert = NULL; } } break; case GNUTLS_BAG_CRL: if (crl == NULL || *crl != NULL) { gnutls_assert(); break; } ret = gnutls_x509_crl_init(crl); if (ret < 0) { gnutls_assert(); goto done; } ret = gnutls_x509_crl_import(*crl, &data, GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert(); gnutls_x509_crl_deinit(*crl); *crl = NULL; goto done; } break; case GNUTLS_BAG_ENCRYPTED: /* XXX Bother to recurse one level down? Unlikely to use the same password anyway. */ case GNUTLS_BAG_EMPTY: default: break; } } idx++; gnutls_pkcs12_bag_deinit(bag); bag = NULL; } if (chain != NULL) { if (_chain_len != 1) { ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto done; } ret = make_chain(&_chain, &_chain_len, &_extra_certs, &_extra_certs_len, flags); if (ret < 0) { gnutls_assert(); goto done; } } ret = 0; done: if (bag) gnutls_pkcs12_bag_deinit(bag); if (ret < 0) { if (*key) { gnutls_x509_privkey_deinit(*key); *key = NULL; } if (crl != NULL && *crl != NULL) { gnutls_x509_crl_deinit(*crl); *crl = NULL; } if (_extra_certs_len && _extra_certs != NULL) { for (i = 0; i < _extra_certs_len; i++) gnutls_x509_crt_deinit(_extra_certs[i]); gnutls_free(_extra_certs); } if (_chain_len && _chain != NULL) { for (i = 0; i < _chain_len; i++) gnutls_x509_crt_deinit(_chain[i]); gnutls_free(_chain); } return ret; } if (extra_certs && _extra_certs_len > 0) { *extra_certs = _extra_certs; *extra_certs_len = _extra_certs_len; } else { if (extra_certs) { *extra_certs = NULL; *extra_certs_len = 0; } for (i = 0; i < _extra_certs_len; i++) gnutls_x509_crt_deinit(_extra_certs[i]); gnutls_free(_extra_certs); } if (chain != NULL) { *chain = _chain; *chain_len = _chain_len; } return ret; }
int tls_revoke_analyzer(requiem_client_profile_t *cp, gnutls_x509_privkey key, gnutls_x509_crt crt, uint64_t revoked_analyzerid) { int ret, i; size_t len, dsize; gnutls_datum data; gnutls_x509_crl crl; uint64_t analyzerid; char crlfile[PATH_MAX], buf[65535]; ret = gnutls_x509_crl_init(&crl); requiem_client_profile_get_tls_server_crl_filename(cp, crlfile, sizeof(crlfile)); ret = access(crlfile, R_OK); if ( ret == 0 ) { ret = _requiem_load_file(crlfile, &data.data, &dsize); if ( ret < 0 ) { fprintf(stderr, "error loading '%s': %s.\n", crlfile, requiem_strerror(ret)); return ret; } data.size = (unsigned int) dsize; ret = gnutls_x509_crl_import(crl, &data, GNUTLS_X509_FMT_PEM); if ( ret < 0 ) { fprintf(stderr, "error importing CRL: %s.\n", gnutls_strerror(ret)); return -1; } } for ( i = 0; i < gnutls_x509_crl_get_crt_count(crl); i++ ) { len = sizeof(analyzerid); gnutls_x509_crl_get_crt_serial(crl, i, (unsigned char *) &analyzerid, &len, NULL); if ( analyzerid == revoked_analyzerid ) return 0; } ret = gnutls_x509_crl_set_crt_serial(crl, &revoked_analyzerid, sizeof(revoked_analyzerid), time(NULL)); if ( ret < 0 ) { fprintf(stderr, "error setting CRL certificate serial: %s.\n", gnutls_strerror(ret)); return -1; } gnutls_x509_crl_set_version(crl, 2); gnutls_x509_crl_set_next_update(crl, time(NULL)); gnutls_x509_crl_set_this_update(crl, time(NULL)); ret = gnutls_x509_crl_sign(crl, crt, key); if ( ret < 0 ) { fprintf(stderr, "error signing CRL: %s.\n", gnutls_strerror(ret)); return -1; } len = sizeof(buf); ret = gnutls_x509_crl_export(crl, GNUTLS_X509_FMT_PEM, buf, &len); if ( ret < 0 ) { fprintf(stderr, "error exporting certificate revocation list: %s\n", gnutls_strerror(ret)); gnutls_x509_crl_deinit(crl); return -1; } gnutls_x509_crl_deinit(crl); unlink(crlfile); ret = save_buf(crlfile, requiem_client_profile_get_uid(cp), requiem_client_profile_get_gid(cp), (unsigned char *) buf, len); if ( ret < 0 ) { fprintf(stderr, "error saving private key.\n"); return -1; } return 1; }
/*- * gnutls_x509_verify_certificate - This function verifies given certificate list * @cert_list: is the certificate list to be verified * @cert_list_length: holds the number of certificate in cert_list * @CA_list: is the CA list which will be used in verification * @CA_list_length: holds the number of CA certificate in CA_list * @CRL_list: not used * @CRL_list_length: not used * * This function will try to verify the given certificate list and return its status (TRUSTED, EXPIRED etc.). * The return value (status) should be one or more of the gnutls_certificate_status_t * enumerated elements bitwise or'd. Note that expiration and activation dates are not checked * by this function, you should check them using the appropriate functions. * * This function understands the basicConstraints (2.5.29.19) PKIX extension. * This means that only a certificate authority can sign a certificate. * * However you must also check the peer's name in order to check if the verified certificate belongs to the * actual peer. * * The return value (status) should be one or more of the gnutls_certificate_status_t * enumerated elements bitwise or'd. * * GNUTLS_CERT_INVALID: the peer's certificate is not valid. * * GNUTLS_CERT_REVOKED: the certificate has been revoked. * * A negative error code is returned in case of an error. * GNUTLS_E_NO_CERTIFICATE_FOUND is returned to indicate that * no certificate was sent by the peer. * * -*/ int gnutls_x509_verify_certificate (const gnutls_datum_t * cert_list, int cert_list_length, const gnutls_datum_t * CA_list, int CA_list_length, const gnutls_datum_t * CRL_list, int CRL_list_length) { unsigned int verify; gnutls_x509_crt_t *peer_certificate_list = NULL; gnutls_x509_crt_t *ca_certificate_list = NULL; gnutls_x509_crl_t *crl_list = NULL; int peer_certificate_list_size = 0, i, x, ret; int ca_certificate_list_size = 0, crl_list_size = 0; if (cert_list == NULL || cert_list_length == 0) return GNUTLS_E_NO_CERTIFICATE_FOUND; /* generate a list of gnutls_certs based on the auth info * raw certs. */ peer_certificate_list_size = cert_list_length; peer_certificate_list = gnutls_calloc (1, peer_certificate_list_size * sizeof (gnutls_x509_crt_t)); if (peer_certificate_list == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } ca_certificate_list_size = CA_list_length; ca_certificate_list = gnutls_calloc (1, ca_certificate_list_size * sizeof (gnutls_x509_crt_t)); if (ca_certificate_list == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } /* allocate memory for CRL */ crl_list_size = CRL_list_length; crl_list = gnutls_calloc (1, crl_list_size * sizeof (gnutls_x509_crl_t)); if (crl_list == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } /* convert certA_list to gnutls_cert* list */ for (i = 0; i < peer_certificate_list_size; i++) { ret = gnutls_x509_crt_init (&peer_certificate_list[i]); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = gnutls_x509_crt_import (peer_certificate_list[i], &cert_list[i], GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert (); goto cleanup; } } /* convert CA_list to gnutls_x509_cert* list */ for (i = 0; i < ca_certificate_list_size; i++) { ret = gnutls_x509_crt_init (&ca_certificate_list[i]); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = gnutls_x509_crt_import (ca_certificate_list[i], &CA_list[i], GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert (); goto cleanup; } } #ifdef ENABLE_PKI /* convert CRL_list to gnutls_x509_crl* list */ for (i = 0; i < crl_list_size; i++) { ret = gnutls_x509_crl_init (&crl_list[i]); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = gnutls_x509_crl_import (crl_list[i], &CRL_list[i], GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert (); goto cleanup; } } #endif /* Verify certificate */ ret = gnutls_x509_crt_list_verify (peer_certificate_list, peer_certificate_list_size, ca_certificate_list, ca_certificate_list_size, crl_list, crl_list_size, 0, &verify); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = verify; cleanup: if (peer_certificate_list != NULL) for (x = 0; x < peer_certificate_list_size; x++) { if (peer_certificate_list[x] != NULL) gnutls_x509_crt_deinit (peer_certificate_list[x]); } if (ca_certificate_list != NULL) for (x = 0; x < ca_certificate_list_size; x++) { if (ca_certificate_list[x] != NULL) gnutls_x509_crt_deinit (ca_certificate_list[x]); } #ifdef ENABLE_PKI if (crl_list != NULL) for (x = 0; x < crl_list_size; x++) { if (crl_list[x] != NULL) gnutls_x509_crl_deinit (crl_list[x]); } gnutls_free (crl_list); #endif gnutls_free (ca_certificate_list); gnutls_free (peer_certificate_list); return ret; }
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_crl_list_import: * @crls: The structures to store the parsed CRLs. Must not be initialized. * @crl_max: Initially must hold the maximum number of crls. It will be updated with the number of crls available. * @data: The PEM encoded CRLs * @format: One of DER or PEM. * @flags: must be zero or an OR'd sequence of gnutls_certificate_import_flags. * * This function will convert the given PEM encoded CRL list * to the native gnutls_x509_crl_t format. The output will be stored * in @crls. They will be automatically initialized. * * If the Certificate is PEM encoded it should have a header of "X509 CRL". * * Returns: the number of certificates read or a negative error value. **/ int gnutls_x509_crl_list_import (gnutls_x509_crl_t * crls, unsigned int *crl_max, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, unsigned int flags) { int size; const char *ptr; gnutls_datum_t tmp; int ret, nocopy = 0; unsigned int count = 0, j; if (format == GNUTLS_X509_FMT_DER) { if (*crl_max < 1) { *crl_max = 1; return GNUTLS_E_SHORT_MEMORY_BUFFER; } count = 1; /* import only the first one */ ret = gnutls_x509_crl_init (&crls[0]); if (ret < 0) { gnutls_assert (); goto error; } ret = gnutls_x509_crl_import (crls[0], data, format); if (ret < 0) { gnutls_assert (); goto error; } *crl_max = 1; return 1; } /* move to the certificate */ ptr = memmem (data->data, data->size, PEM_CRL_SEP, sizeof (PEM_CRL_SEP) - 1); if (ptr == NULL) { gnutls_assert (); return GNUTLS_E_BASE64_DECODING_ERROR; } count = 0; do { if (count >= *crl_max) { if (!(flags & GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED)) break; else nocopy = 1; } if (!nocopy) { ret = gnutls_x509_crl_init (&crls[count]); if (ret < 0) { gnutls_assert (); goto error; } tmp.data = (void *) ptr; tmp.size = data->size - (ptr - (char *) data->data); ret = gnutls_x509_crl_import (crls[count], &tmp, GNUTLS_X509_FMT_PEM); if (ret < 0) { gnutls_assert (); goto error; } } /* now we move ptr after the pem header */ ptr++; /* find the next certificate (if any) */ size = data->size - (ptr - (char *) data->data); if (size > 0) { ptr = memmem (ptr, size, PEM_CRL_SEP, sizeof (PEM_CRL_SEP) - 1); } else ptr = NULL; count++; } while (ptr != NULL); *crl_max = count; if (nocopy == 0) return count; else return GNUTLS_E_SHORT_MEMORY_BUFFER; error: for (j = 0; j < count; j++) gnutls_x509_crl_deinit (crls[j]); return ret; }
~RAIICRL() { gnutls_x509_crl_deinit(crl); }
/** * gnutls_certificate_set_x509_simple_pkcs12_mem: * @res: is a #gnutls_certificate_credentials_t type. * @p12blob: the PKCS#12 blob. * @type: is PEM or DER of the @pkcs12file. * @password: optional password used to decrypt PKCS#12 file, bags and keys. * * This function sets a certificate/private key pair and/or a CRL in * the gnutls_certificate_credentials_t type. This function may * be called more than once (in case multiple keys/certificates exist * for the server). * * Encrypted PKCS#12 bags and PKCS#8 private keys are supported. However, * only password based security, and the same password for all * operations, are supported. * * PKCS#12 file may contain many keys and/or certificates, and this * function will try to auto-detect based on the key ID the certificate * and key pair to use. If the PKCS#12 file contain the issuer of * the selected certificate, it will be appended to the certificate * to form a chain. * * If more than one private keys are stored in the PKCS#12 file, * then only one key will be read (and it is undefined which one). * * It is believed that the limitations of this function is acceptable * for most usage, and that any more flexibility would introduce * complexity that would make it harder to use this functionality at * all. * * Note that, this function by default returns zero on success and a negative value on error. * Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags() * it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair. * * Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior). * * Since: 2.8.0 **/ int gnutls_certificate_set_x509_simple_pkcs12_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t * p12blob, gnutls_x509_crt_fmt_t type, const char *password) { gnutls_pkcs12_t p12; gnutls_x509_privkey_t key = NULL; gnutls_x509_crt_t *chain = NULL; gnutls_x509_crl_t crl = NULL; unsigned int chain_size = 0, i; int ret, idx; ret = gnutls_pkcs12_init(&p12); if (ret < 0) { gnutls_assert(); return ret; } ret = gnutls_pkcs12_import(p12, p12blob, type, 0); if (ret < 0) { gnutls_assert(); gnutls_pkcs12_deinit(p12); return ret; } if (password) { ret = gnutls_pkcs12_verify_mac(p12, password); if (ret < 0) { gnutls_assert(); gnutls_pkcs12_deinit(p12); return ret; } } ret = gnutls_pkcs12_simple_parse(p12, password, &key, &chain, &chain_size, NULL, NULL, &crl, 0); gnutls_pkcs12_deinit(p12); if (ret < 0) { gnutls_assert(); return ret; } if (key && chain) { ret = gnutls_certificate_set_x509_key(res, chain, chain_size, key); if (ret < 0) { gnutls_assert(); goto done; } idx = ret; } else { gnutls_assert(); ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto done; } if (crl) { ret = gnutls_certificate_set_x509_crl(res, &crl, 1); if (ret < 0) { gnutls_assert(); goto done; } } if (res->flags & GNUTLS_CERTIFICATE_API_V2) ret = idx; else ret = 0; done: if (chain) { for (i = 0; i < chain_size; i++) gnutls_x509_crt_deinit(chain[i]); gnutls_free(chain); } if (key) gnutls_x509_privkey_deinit(key); if (crl) gnutls_x509_crl_deinit(crl); return ret; }
/** * 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; }