/**
 * 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;
}
Beispiel #3
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);
}
Beispiel #4
0
/**
 * 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;
}
Beispiel #5
0
/**
 * 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;
}
Beispiel #7
0
/*-
  * 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;
}
Beispiel #8
0
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);
}
Beispiel #9
0
/**
 * 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);
			}
Beispiel #11
0
/**
 * 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;
}
Beispiel #12
0
/**
 * 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;
}