Esempio n. 1
0
/**
 * gnutls_certificate_free_keys:
 * @sc: is a #gnutls_certificate_credentials_t structure.
 *
 * This function will delete all the keys and the certificates associated
 * with the given credentials. This function must not be called when a
 * TLS negotiation that uses the credentials is in progress.
 *
 **/
void
gnutls_certificate_free_keys (gnutls_certificate_credentials_t sc)
{
  unsigned i, j;

  for (i = 0; i < sc->ncerts; i++)
    {
      for (j = 0; j < sc->certs[i].cert_list_length; j++)
        {
          gnutls_pcert_deinit (&sc->certs[i].cert_list[j]);
        }
      gnutls_free (sc->certs[i].cert_list);
      _gnutls_str_array_clear (&sc->certs[i].names);
    }

  gnutls_free (sc->certs);
  sc->certs = NULL;

  for (i = 0; i < sc->ncerts; i++)
    {
      gnutls_privkey_deinit (sc->pkey[i]);
    }

  gnutls_free (sc->pkey);
  sc->pkey = NULL;

  sc->ncerts = 0;
}
Esempio n. 2
0
/* Returns the name of the certificate of a null name
 */
int _gnutls_get_x509_name(gnutls_x509_crt_t crt, gnutls_str_array_t * names)
{
	size_t max_size;
	int i, ret = 0, ret2;
	char name[MAX_CN];
	unsigned have_dns_name = 0;

	for (i = 0; !(ret < 0); i++) {
		max_size = sizeof(name);

		ret =
		    gnutls_x509_crt_get_subject_alt_name(crt, i, name,
							 &max_size, NULL);
		if (ret == GNUTLS_SAN_DNSNAME) {
			have_dns_name = 1;

			ret2 =
			    _gnutls_str_array_append_idna(names, name,
						  max_size);
			if (ret2 < 0) {
				_gnutls_str_array_clear(names);
				return gnutls_assert_val(ret2);
			}
		}
	}

	if (have_dns_name == 0) {
		max_size = sizeof(name);
		ret =
		    gnutls_x509_crt_get_dn_by_oid(crt, OID_X520_COMMON_NAME, 0, 0,
						  name, &max_size);
		if (ret >= 0) {
			ret = _gnutls_str_array_append_idna(names, name, max_size);
			if (ret < 0) {
				_gnutls_str_array_clear(names);
				return gnutls_assert_val(ret);
			}
		}
	}

	return 0;
}
Esempio n. 3
0
/**
 * gnutls_certificate_set_x509_key:
 * @res: is a #gnutls_certificate_credentials_t type.
 * @cert_list: contains a certificate list (path) for the specified private key
 * @cert_list_size: holds the size of the certificate list
 * @key: is a #gnutls_x509_privkey_t key
 *
 * This function sets a certificate/private key pair in the
 * gnutls_certificate_credentials_t type.  This function may be
 * called more than once, in case multiple keys/certificates exist for
 * the server.  For clients that wants to send more than their own end
 * entity certificate (e.g., also an intermediate CA cert) then put
 * the certificate chain in @cert_list.
 *
 * Note that the certificates and keys provided, can be safely deinitialized
 * after this function is called.
 *
 * If that function fails to load the @res type is at an undefined state, it must
 * not be reused to load other keys or certificates.
 *
 * 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.4.0
 **/
int
gnutls_certificate_set_x509_key(gnutls_certificate_credentials_t res,
				gnutls_x509_crt_t * cert_list,
				int cert_list_size,
				gnutls_x509_privkey_t key)
{
	int ret;
	gnutls_privkey_t pkey;
	gnutls_pcert_st *pcerts = NULL;
	gnutls_str_array_t names;

	_gnutls_str_array_init(&names);

	/* this should be first
	 */
	ret = gnutls_privkey_init(&pkey);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	if (res->pin.cb)
		gnutls_privkey_set_pin_function(pkey, res->pin.cb,
						res->pin.data);

	ret =
	    gnutls_privkey_import_x509(pkey, key,
				       GNUTLS_PRIVKEY_IMPORT_COPY);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* load certificates */
	pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * cert_list_size);
	if (pcerts == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = _gnutls_get_x509_name(cert_list[0], &names);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
		gnutls_pcert_import_x509_list(pcerts, cert_list, (unsigned int*)&cert_list_size,
					      GNUTLS_X509_CRT_LIST_SORT);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    _gnutls_certificate_credential_append_keypair(res, pkey, names, pcerts,
						   cert_list_size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	res->ncerts++;

	/* after this point we do not deinitialize anything on failure to avoid
	 * double freeing. We intentionally keep everything as the credentials state
	 * is documented to be on undefined state. */
	if ((ret = _gnutls_check_key_cert_match(res)) < 0) {
		gnutls_assert();
		return ret;
	}

	CRED_RET_SUCCESS(res);

      cleanup:
	gnutls_free(pcerts);
	_gnutls_str_array_clear(&names);
	return ret;
}
Esempio n. 4
0
/* Reads a certificate key from a token.
 */
static int
read_cert_url(gnutls_certificate_credentials_t res, gnutls_privkey_t key, const char *url)
{
	int ret;
	gnutls_x509_crt_t crt = NULL;
	gnutls_pcert_st *ccert = NULL;
	gnutls_str_array_t names;
	gnutls_datum_t t = {NULL, 0};
	unsigned i, count = 0;

	_gnutls_str_array_init(&names);

	ccert = gnutls_malloc(sizeof(*ccert)*MAX_PKCS11_CERT_CHAIN);
	if (ccert == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	ret = gnutls_x509_crt_init(&crt);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (res->pin.cb)
		gnutls_x509_crt_set_pin_function(crt, res->pin.cb,
						 res->pin.data);

	ret = gnutls_x509_crt_import_url(crt, url, 0);
	if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
		ret =
		    gnutls_x509_crt_import_url(crt, url,
					       GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_get_x509_name(crt, &names);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Try to load the whole certificate chain from the PKCS #11 token */
	for (i=0;i<MAX_PKCS11_CERT_CHAIN;i++) {
		ret = gnutls_x509_crt_check_issuer(crt, crt);
		if (i > 0 && ret != 0) {
			/* self signed */
			break;
		}

		ret = gnutls_pcert_import_x509(&ccert[i], crt, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
		count++;

		ret = _gnutls_get_raw_issuer(url, crt, &t, 0);
		if (ret < 0)
			break;

		gnutls_x509_crt_deinit(crt);
		crt = NULL;
		ret = gnutls_x509_crt_init(&crt);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_x509_crt_import(crt, &t, GNUTLS_X509_FMT_DER);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
		gnutls_free(t.data);
	}

	ret = _gnutls_certificate_credential_append_keypair(res, key, names, ccert, count);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (crt != NULL)
		gnutls_x509_crt_deinit(crt);

	return 0;
cleanup:
	if (crt != NULL)
		gnutls_x509_crt_deinit(crt);
	gnutls_free(t.data);
	_gnutls_str_array_clear(&names);
	gnutls_free(ccert);
	return ret;
}
Esempio n. 5
0
/* Reads a base64 encoded certificate list from memory and stores it to
 * a gnutls_cert structure. Returns the number of certificate parsed.
 */
static int
parse_pem_cert_mem(gnutls_certificate_credentials_t res,
		   gnutls_privkey_t key,
		   const char *input_cert, int input_cert_size)
{
	int size;
	const char *ptr;
	gnutls_datum_t tmp;
	int ret, count, i;
	unsigned ncerts = 0;
	gnutls_pcert_st *pcerts = NULL;
	gnutls_str_array_t names;
	gnutls_x509_crt_t unsorted[DEFAULT_MAX_VERIFY_DEPTH];

	_gnutls_str_array_init(&names);

	/* move to the certificate
	 */
	ptr = memmem(input_cert, input_cert_size,
		     PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1);
	if (ptr == NULL)
		ptr = memmem(input_cert, input_cert_size,
			     PEM_CERT_SEP2, sizeof(PEM_CERT_SEP2) - 1);

	if (ptr == NULL) {
		gnutls_assert();
		return GNUTLS_E_BASE64_DECODING_ERROR;
	}
	size = input_cert_size - (ptr - input_cert);

	count = 0;

	do {
		tmp.data = (void *) ptr;
		tmp.size = size;

		ret = gnutls_x509_crt_init(&unsorted[count]);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_x509_crt_import(unsorted[count], &tmp, GNUTLS_X509_FMT_PEM);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
		count++;

		/* now we move ptr after the pem header
		 */
		ptr++;
		size--;

		/* find the next certificate (if any)
		 */

		if (size > 0) {
			char *ptr3;

			ptr3 =
			    memmem(ptr, size, PEM_CERT_SEP,
				   sizeof(PEM_CERT_SEP) - 1);
			if (ptr3 == NULL)
				ptr3 = memmem(ptr, size, PEM_CERT_SEP2,
					      sizeof(PEM_CERT_SEP2) - 1);

			ptr = ptr3;
			size = input_cert_size - (ptr - input_cert);
		} else
			ptr = NULL;

	}
	while (ptr != NULL && count < DEFAULT_MAX_VERIFY_DEPTH);

	ret =
	    _gnutls_get_x509_name(unsorted[0], &names);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * count);
	if (pcerts == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ncerts = count;
	ret =
	    gnutls_pcert_import_x509_list(pcerts, unsorted, &ncerts, GNUTLS_X509_CRT_LIST_SORT);
	if (ret < 0) {
		gnutls_free(pcerts);
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    _gnutls_certificate_credential_append_keypair(res, key, names, pcerts, ncerts);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	for (i = 0; i < count; i++)
		gnutls_x509_crt_deinit(unsorted[i]);

	return ncerts;

      cleanup:
	_gnutls_str_array_clear(&names);
	for (i = 0; i < count; i++)
		gnutls_x509_crt_deinit(unsorted[i]);
	if (pcerts) {
		for (i = 0; i < count; i++)
			gnutls_pcert_deinit(&pcerts[i]);
		gnutls_free(pcerts);
	}
	return ret;
}
Esempio n. 6
0
/* Reads a DER encoded certificate list from memory and stores it to a
 * gnutls_cert structure. Returns the number of certificates parsed.
 */
static int
parse_der_cert_mem(gnutls_certificate_credentials_t res,
		   gnutls_privkey_t key,
		   const void *input_cert, int input_cert_size)
{
	gnutls_datum_t tmp;
	gnutls_x509_crt_t crt;
	gnutls_pcert_st *ccert;
	int ret;
	gnutls_str_array_t names;

	_gnutls_str_array_init(&names);

	ccert = gnutls_malloc(sizeof(*ccert));
	if (ccert == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = gnutls_x509_crt_init(&crt);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	tmp.data = (uint8_t *) input_cert;
	tmp.size = input_cert_size;

	ret = gnutls_x509_crt_import(crt, &tmp, GNUTLS_X509_FMT_DER);
	if (ret < 0) {
		gnutls_assert();
		gnutls_x509_crt_deinit(crt);
		goto cleanup;
	}

	ret = _gnutls_get_x509_name(crt, &names);
	if (ret < 0) {
		gnutls_assert();
		gnutls_x509_crt_deinit(crt);
		goto cleanup;
	}

	ret = gnutls_pcert_import_x509(ccert, crt, 0);
	gnutls_x509_crt_deinit(crt);

	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_certificate_credential_append_keypair(res, key, names, ccert, 1);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	return ret;

      cleanup:
	_gnutls_str_array_clear(&names);
	gnutls_free(ccert);
	return ret;
}