예제 #1
0
gboolean li_gnutls_ocsp_search_datum(liServer *srv, liGnuTLSOCSP *ocsp, gnutls_datum_t const* file) {
	int r;
	gnutls_datum_t decoded = { NULL, 0 };
	gboolean result = FALSE;

	r = gnutls_pem_base64_decode_alloc("OCSP RESPONSE", file, &decoded);

	if (GNUTLS_E_SUCCESS <= r) {
		result = add_response(srv, ocsp, &decoded);
		if (!result) {
			ERROR(srv, "%s", "Failed loading OCSP response from PEM block");
			goto error;
		}
	} else if (GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR == r) {
		/* ignore GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR */
	} else {
		ERROR(srv, "gnutls_pem_base64_decode_alloc failed to decode OCSP RESPONSE from PEM block (%s): %s",
			gnutls_strerror_name(r), gnutls_strerror(r));
		/* continue anyway */
	}
	result = TRUE;

error:
	gnutls_free(decoded.data);
	return result;
}
예제 #2
0
/* this bit is based on read_ca_file() in gnutls */
static int tls_compare_certificates (const gnutls_datum *peercert)
{
  gnutls_datum cert;
  unsigned char *ptr;
  FILE *fd1;
  int ret;
  gnutls_datum b64_data;
  unsigned char *b64_data_data;
  struct stat filestat;

  if (stat(SslCertFile, &filestat) == -1)
    return 0;

  b64_data.size = filestat.st_size+1;
  b64_data_data = (unsigned char *) safe_calloc (1, b64_data.size);
  b64_data_data[b64_data.size-1] = '\0';
  b64_data.data = b64_data_data;

  fd1 = fopen(SslCertFile, "r");
  if (fd1 == NULL) {
    return 0;
  }

  b64_data.size = fread(b64_data.data, 1, b64_data.size, fd1);
  fclose(fd1);

  do {
    ret = gnutls_pem_base64_decode_alloc(NULL, &b64_data, &cert);
    if (ret != 0)
    {
      FREE (&b64_data_data);
      return 0;
    }

    ptr = (unsigned char *)strstr((char*)b64_data.data, CERT_SEP) + 1;
    ptr = (unsigned char *)strstr((char*)ptr, CERT_SEP);

    b64_data.size = b64_data.size - (ptr - b64_data.data);
    b64_data.data = ptr;

    if (cert.size == peercert->size)
    {
      if (memcmp (cert.data, peercert->data, cert.size) == 0)
      {
	/* match found */
        gnutls_free(cert.data);
	FREE (&b64_data_data);
	return 1;
      }
    }

    gnutls_free(cert.data);
  } while (ptr != NULL);

  /* no match found */
  FREE (&b64_data_data);
  return 0;
}
예제 #3
0
gboolean li_gnutls_ocsp_add(liServer *srv, liGnuTLSOCSP *ocsp, const char* filename) {
	int r;
	gnutls_datum_t file = { NULL, 0 };
	gnutls_datum_t decoded = { NULL, 0 };
	gnutls_datum_t* der_data;
	gboolean result = FALSE;

	if (GNUTLS_E_SUCCESS > (r = gnutls_load_file(filename, &file))) {
		ERROR(srv, "Failed to load OCSP file '%s' (%s): %s",
				filename,
				gnutls_strerror_name(r), gnutls_strerror(r));
		goto error;
	}

	/* decode pem "-----BEGIN OCSP RESPONSE-----", otherwise expect DER */
	if (file.size > 20 && 0 == memcmp(file.data, CONST_STR_LEN("-----BEGIN "))) {
		r = gnutls_pem_base64_decode_alloc("OCSP RESPONSE", &file, &decoded);

		if (GNUTLS_E_SUCCESS > r) {
			ERROR(srv, "gnutls_pem_base64_decode_alloc failed to decode OCSP RESPONSE from '%s' (%s): %s",
				filename,
				gnutls_strerror_name(r), gnutls_strerror(r));
			goto error;
		}
		der_data = &decoded;
	} else {
		der_data = &file;
	}

	result = add_response(srv, ocsp, der_data);
	if (!result) {
		ERROR(srv, "Failed loading OCSP response from '%s'", filename);
	}

error:
	gnutls_free(file.data);
	gnutls_free(decoded.data);
	return result;
}
예제 #4
0
int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata,
		 gnutls_privkey_t *pkey, gnutls_datum_t *pkey_sig)
{
	static const TSS_UUID SRK_UUID = TSS_UUID_SRK;
	gnutls_datum_t asn1;
	unsigned int tss_len;
	char *pass;
	int ofs, err;

	err = gnutls_pem_base64_decode_alloc("TSS KEY BLOB", fdata, &asn1);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Error decoding TSS key blob: %s\n"),
			     gnutls_strerror(err));
		return -EINVAL;
	}
	/* Ick. We have to parse the ASN1 OCTET_STRING for ourselves. */
	if (asn1.size < 2 || asn1.data[0] != 0x04 /* OCTET_STRING */) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Error in TSS key blob\n"));
		goto out_blob;
	}

	tss_len = asn1.data[1];
	ofs = 2;
	if (tss_len & 0x80) {
		int lenlen = tss_len & 0x7f;

		if (asn1.size < 2 + lenlen || lenlen > 3) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Error in TSS key blob\n"));
			goto out_blob;
		}

		tss_len = 0;
		while (lenlen) {
			tss_len <<= 8;
			tss_len |= asn1.data[ofs++];
			lenlen--;
		}
	}
	if (tss_len + ofs != asn1.size) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Error in TSS key blob\n"));
		goto out_blob;
	}

	err = Tspi_Context_Create(&vpninfo->tpm_context);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to create TPM context: %s\n"),
			     Trspi_Error_String(err));
		goto out_blob;
	}
	err = Tspi_Context_Connect(vpninfo->tpm_context, NULL);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to connect TPM context: %s\n"),
			     Trspi_Error_String(err));
		goto out_context;
	}
	err = Tspi_Context_LoadKeyByUUID(vpninfo->tpm_context, TSS_PS_TYPE_SYSTEM,
					 SRK_UUID, &vpninfo->srk);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to load TPM SRK key: %s\n"),
			     Trspi_Error_String(err));
		goto out_context;
	}
	err = Tspi_GetPolicyObject(vpninfo->srk, TSS_POLICY_USAGE, &vpninfo->srk_policy);
	if (err) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to load TPM SRK policy object: %s\n"),
			     Trspi_Error_String(err));
		goto out_srk;
	}

	pass = vpninfo->cert_password;
	vpninfo->cert_password = NULL;
	while (1) {
		static const char nullpass[20];

		/* We don't seem to get the error here... */
		if (pass)
			err = Tspi_Policy_SetSecret(vpninfo->srk_policy,
						    TSS_SECRET_MODE_PLAIN,
						    strlen(pass), (BYTE *)pass);
		else /* Well-known NULL key */
			err = Tspi_Policy_SetSecret(vpninfo->srk_policy,
						    TSS_SECRET_MODE_SHA1,
						    sizeof(nullpass), (BYTE *)nullpass);
		if (err) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Failed to set TPM PIN: %s\n"),
				     Trspi_Error_String(err));
			goto out_srkpol;
		}

		free(pass);

		/* ... we get it here instead. */
		err = Tspi_Context_LoadKeyByBlob(vpninfo->tpm_context, vpninfo->srk,
						 tss_len, asn1.data + ofs,
						 &vpninfo->tpm_key);
		if (!err)
			break;

		if (pass)
			vpn_progress(vpninfo, PRG_ERR,
				     _("Failed to load TPM key blob: %s\n"),
				     Trspi_Error_String(err));

		if (err != TPM_E_AUTHFAIL)
			goto out_srkpol;

		err = request_passphrase(vpninfo, "openconnect_tpm_srk",
					 &pass, _("Enter TPM SRK PIN:"));
		if (err)
			goto out_srkpol;
	}

#ifdef HAVE_GNUTLS_CERTIFICATE_SET_KEY
	gnutls_privkey_init(pkey);
	/* This would be nicer if there was a destructor callback. I could
	   allocate a data structure with the TPM handles and the vpninfo
	   pointer, and destroy that properly when the key is destroyed. */
	gnutls_privkey_import_ext(*pkey, GNUTLS_PK_RSA, vpninfo, tpm_sign_fn, NULL, 0);
#else
	*pkey = OPENCONNECT_TPM_PKEY;
#endif

 retry_sign:
	err = sign_dummy_data(vpninfo, *pkey, fdata, pkey_sig);
	if (err == GNUTLS_E_INSUFFICIENT_CREDENTIALS) {
		if (!vpninfo->tpm_key_policy) {
			err = Tspi_Context_CreateObject(vpninfo->tpm_context,
							TSS_OBJECT_TYPE_POLICY,
							TSS_POLICY_USAGE,
							&vpninfo->tpm_key_policy);
			if (err) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to create key policy object: %s\n"),
					     Trspi_Error_String(err));
				goto out_key;
			}
			err = Tspi_Policy_AssignToObject(vpninfo->tpm_key_policy,
							 vpninfo->tpm_key);
			if (err) {
				vpn_progress(vpninfo, PRG_ERR,
					     _("Failed to assign policy to key: %s\n"),
					     Trspi_Error_String(err));
				goto out_key_policy;
			}
		}
	        err = request_passphrase(vpninfo, "openconnect_tpm_key",
					 &pass, _("Enter TPM key PIN:"));
		if (err)
			goto out_key_policy;

		err = Tspi_Policy_SetSecret(vpninfo->tpm_key_policy,
					    TSS_SECRET_MODE_PLAIN,
					    strlen(pass), (void *)pass);
		free (pass);

		if (err) {
			vpn_progress(vpninfo, PRG_ERR,
				     _("Failed to set key PIN: %s\n"),
				     Trspi_Error_String(err));
			goto out_key_policy;
		}
		goto retry_sign;
	}

	free (asn1.data);
	return 0;
 out_key_policy:
	Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key_policy);
	vpninfo->tpm_key_policy = 0;
 out_key:
	Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->tpm_key);
	vpninfo->tpm_key = 0;
 out_srkpol:
	Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk_policy);
	vpninfo->srk_policy = 0;
 out_srk:
	Tspi_Context_CloseObject(vpninfo->tpm_context, vpninfo->srk);
	vpninfo->srk = 0;
 out_context:
	Tspi_Context_Close(vpninfo->tpm_context);
	vpninfo->tpm_context = 0;
 out_blob:
	free (asn1.data);
	return -EIO;
}
예제 #5
0
void doit(void)
{
	gnutls_datum_t der_cert, der_cert2;
	int ret;
	gnutls_datum_t hash;

	/* the sha1 hash of the server's pubkey */
	hash.data = (void *) SHA1_HASH;
	hash.size = sizeof(SHA1_HASH) - 1;

	/* General init. */
	global_init();
	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(2);

	ret =
	    gnutls_pem_base64_decode_alloc("CERTIFICATE", &server_cert,
					   &der_cert);
	if (ret < 0) {
		fail("base64 decoding\n");
		goto fail;
	}

	ret =
	    gnutls_pem_base64_decode_alloc("CERTIFICATE", &client_cert,
					   &der_cert2);
	if (ret < 0) {
		fail("base64 decoding\n");
		goto fail;
	}

	remove(TMP_FILE);

	/* verify whether the stored hash verification succeeeds */
	ret = gnutls_store_commitment(TMP_FILE, NULL, "localhost", "https",
				      GNUTLS_DIG_SHA1, &hash, 0, 0);
	if (ret != 0) {
		fail("commitment storage: %s\n", gnutls_strerror(ret));
		goto fail;
	}

	if (debug)
		success("Commitment storage: passed\n");

	ret =
	    gnutls_verify_stored_pubkey(TMP_FILE, NULL, "localhost",
					"https", GNUTLS_CRT_X509,
					&der_cert, 0);
	remove(TMP_FILE);

	if (ret != 0) {
		fail("commitment verification: %s\n",
		     gnutls_strerror(ret));
		goto fail;
	}

	if (debug)
		success("Commitment verification: passed\n");

	/* verify whether the stored pubkey verification succeeeds */
	ret = gnutls_store_pubkey(TMP_FILE, NULL, "localhost", "https",
				  GNUTLS_CRT_X509, &der_cert, 0, 0);
	if (ret != 0) {
		fail("storage: %s\n", gnutls_strerror(ret));
		goto fail;
	}

	if (debug)
		success("Public key storage: passed\n");

	ret =
	    gnutls_verify_stored_pubkey(TMP_FILE, NULL, "localhost",
					"https", GNUTLS_CRT_X509,
					&der_cert, 0);
	if (ret != 0) {
		fail("pubkey verification: %s\n", gnutls_strerror(ret));
		goto fail;
	}

	ret =
	    gnutls_verify_stored_pubkey(TMP_FILE, NULL, "localhost",
					"https", GNUTLS_CRT_X509,
					&der_cert2, 0);
	remove(TMP_FILE);
	if (ret == 0) {
		fail("verification succeed when shouldn't!\n");
		goto fail;
	}
	if (ret != GNUTLS_E_CERTIFICATE_KEY_MISMATCH) {
		fail("Wrong error code returned: %s!\n",
		     gnutls_strerror(ret));
		goto fail;
	}

	if (debug)
		success("Public key verification: passed\n");


	gnutls_global_deinit();
	gnutls_free(der_cert.data);
	gnutls_free(der_cert2.data);

	return;
      fail:
	remove(TMP_FILE);
	exit(1);
}
예제 #6
0
파일: tpm.c 프로젝트: randombit/hacrypto
static int load_key(TSS_HCONTEXT tpm_ctx, TSS_HKEY srk,
		    const gnutls_datum_t * fdata,
		    gnutls_tpmkey_fmt_t format, TSS_HKEY * tpm_key)
{
	int ret, err;
	gnutls_datum_t asn1 = { NULL, 0 };

	if (format == GNUTLS_TPMKEY_FMT_CTK_PEM) {
		gnutls_datum_t td;

		ret =
		    gnutls_pem_base64_decode_alloc("TSS KEY BLOB", fdata,
						   &asn1);
		if (ret) {
			gnutls_assert();
			_gnutls_debug_log
			    ("Error decoding TSS key blob: %s\n",
			     gnutls_strerror(ret));
			return ret;
		}

		ret =
		    _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
					       asn1.data, asn1.size, &td);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
		gnutls_free(asn1.data);
		asn1.data = td.data;
		asn1.size = td.size;
	} else {		/* DER */

		UINT32 tint2;
		UINT32 type;

		asn1.size = fdata->size;
		asn1.data = gnutls_malloc(asn1.size);
		if (asn1.data == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}

		tint2 = asn1.size;
		err =
		    Tspi_DecodeBER_TssBlob(fdata->size, fdata->data, &type,
					   &tint2, asn1.data);
		if (err != 0) {
			gnutls_assert();
			ret = tss_err(err);
			goto cleanup;
		}

		asn1.size = tint2;
	}

	/* ... we get it here instead. */
	err = Tspi_Context_LoadKeyByBlob(tpm_ctx, srk,
					 asn1.size, asn1.data, tpm_key);
	if (err != 0) {
		gnutls_assert();
		ret = tss_err(err);
		goto cleanup;
	}

	ret = 0;

      cleanup:
	gnutls_free(asn1.data);

	return ret;
}
예제 #7
0
파일: ssl_gnutls.c 프로젝트: darnir/neomutt
/**
 * tls_compare_certificates - Compare certificates against #C_CertificateFile
 * @param peercert Certificate
 * @retval 1 Certificate matches file
 * @retval 0 Error, or no match
 */
static int tls_compare_certificates(const gnutls_datum_t *peercert)
{
  gnutls_datum_t cert;
  unsigned char *ptr = NULL;
  gnutls_datum_t b64_data;
  unsigned char *b64_data_data = NULL;
  struct stat filestat;

  if (stat(C_CertificateFile, &filestat) == -1)
    return 0;

  b64_data.size = filestat.st_size + 1;
  b64_data_data = mutt_mem_calloc(1, b64_data.size);
  b64_data_data[b64_data.size - 1] = '\0';
  b64_data.data = b64_data_data;

  FILE *fp = fopen(C_CertificateFile, "r");
  if (!fp)
    return 0;

  b64_data.size = fread(b64_data.data, 1, b64_data.size, fp);
  mutt_file_fclose(&fp);

  do
  {
    const int ret = gnutls_pem_base64_decode_alloc(NULL, &b64_data, &cert);
    if (ret != 0)
    {
      FREE(&b64_data_data);
      return 0;
    }

    /* find start of cert, skipping junk */
    ptr = (unsigned char *) strstr((char *) b64_data.data, CERT_SEP);
    if (!ptr)
    {
      gnutls_free(cert.data);
      FREE(&b64_data_data);
      return 0;
    }
    /* find start of next cert */
    ptr = (unsigned char *) strstr((char *) ptr + 1, CERT_SEP);

    b64_data.size = b64_data.size - (ptr - b64_data.data);
    b64_data.data = ptr;

    if (cert.size == peercert->size)
    {
      if (memcmp(cert.data, peercert->data, cert.size) == 0)
      {
        /* match found */
        gnutls_free(cert.data);
        FREE(&b64_data_data);
        return 1;
      }
    }

    gnutls_free(cert.data);
  } while (ptr);

  /* no match found */
  FREE(&b64_data_data);
  return 0;
}