Exemplo n.º 1
0
/**
 * gnutls_tpm_privkey_delete:
 * @url: the URL describing the key
 * @srk_password: a password for the SRK key
 *
 * This function will unregister the private key from the TPM
 * chip. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.1.0
 **/
int gnutls_tpm_privkey_delete(const char *url, const char *srk_password)
{
	struct tpm_ctx_st s;
	struct tpmkey_url_st durl;
	TSS_RESULT tssret;
	TSS_HKEY tkey;
	int ret;

	ret = decode_tpmkey_url(url, &durl);
	if (ret < 0)
		return gnutls_assert_val(ret);

	if (durl.uuid_set == 0)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	ret = tpm_open_session(&s, srk_password);
	if (ret < 0)
		return gnutls_assert_val(ret);

	tssret =
	    Tspi_Context_UnregisterKey(s.tpm_ctx, durl.storage, durl.uuid,
				       &tkey);
	if (tssret != 0) {
		gnutls_assert();
		ret = tss_err(tssret);
		goto err_cc;
	}

	ret = 0;
      err_cc:
	tpm_close_session(&s);
	return ret;
}
Exemplo n.º 2
0
static void tpm_deinit_fn(gnutls_privkey_t key, void *_s)
{
	struct tpm_ctx_st *s = _s;

	Tspi_Context_CloseObject(s->tpm_ctx, s->tpm_key_policy);
	Tspi_Context_CloseObject(s->tpm_ctx, s->tpm_key);

	tpm_close_session(s);
	gnutls_free(s);
}
Exemplo n.º 3
0
static int
import_tpm_pubkey(gnutls_pubkey_t pkey,
		  const gnutls_datum_t * fdata,
		  gnutls_tpmkey_fmt_t format,
		  TSS_UUID * uuid,
		  TSS_FLAG storage, const char *srk_password)
{
	int err, ret;
	struct tpm_ctx_st s;

	ret = tpm_open_session(&s, srk_password);
	if (ret < 0)
		return gnutls_assert_val(ret);

	if (fdata != NULL) {
		ret =
		    load_key(s.tpm_ctx, s.srk, fdata, format, &s.tpm_key);
		if (ret < 0) {
			gnutls_assert();
			goto out_session;
		}
	} else if (uuid) {
		err =
		    Tspi_Context_LoadKeyByUUID(s.tpm_ctx, storage,
					       *uuid, &s.tpm_key);
		if (err) {
			gnutls_assert();
			ret = tss_err(err);
			goto out_session;
		}
	} else {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		goto out_session;
	}

	ret = read_pubkey(pkey, s.tpm_key, NULL);
	if (ret < 0) {
		gnutls_assert();
		goto out_session;
	}

	ret = 0;
      out_session:
	tpm_close_session(&s);
	return ret;
}
Exemplo n.º 4
0
static int
import_tpm_key(gnutls_privkey_t pkey,
	       const gnutls_datum_t * fdata,
	       gnutls_tpmkey_fmt_t format,
	       TSS_UUID * uuid,
	       TSS_FLAG storage,
	       const char *srk_password, const char *key_password)
{
	int err, ret;
	struct tpm_ctx_st *s;
	gnutls_datum_t tmp_sig;

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

	ret = tpm_open_session(s, srk_password);
	if (ret < 0) {
		gnutls_assert();
		goto out_ctx;
	}

	if (fdata != NULL) {
		ret =
		    load_key(s->tpm_ctx, s->srk, fdata, format,
			     &s->tpm_key);
		if (ret < 0) {
			gnutls_assert();
			goto out_session;
		}
	} else if (uuid) {
		err =
		    Tspi_Context_LoadKeyByUUID(s->tpm_ctx, storage,
					       *uuid, &s->tpm_key);

		if (err) {
			gnutls_assert();
			ret = tss_err(err);
			goto out_session;
		}
	} else {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		goto out_session;
	}

	ret =
	    gnutls_privkey_import_ext2(pkey, GNUTLS_PK_RSA, s,
				       tpm_sign_fn, NULL, tpm_deinit_fn,
				       0);
	if (ret < 0) {
		gnutls_assert();
		goto out_session;
	}

	ret =
	    gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA1, 0, &nulldata,
				     &tmp_sig);
	if (ret == GNUTLS_E_TPM_KEY_PASSWORD_ERROR) {
		if (!s->tpm_key_policy) {
			err = Tspi_Context_CreateObject(s->tpm_ctx,
							TSS_OBJECT_TYPE_POLICY,
							TSS_POLICY_USAGE,
							&s->
							tpm_key_policy);
			if (err) {
				gnutls_assert();
				ret = tss_err(err);
				goto out_key;
			}

			err =
			    Tspi_Policy_AssignToObject(s->tpm_key_policy,
						       s->tpm_key);
			if (err) {
				gnutls_assert();
				ret = tss_err(err);
				goto out_key_policy;
			}
		}

		err = myTspi_Policy_SetSecret(s->tpm_key_policy,
					      SAFE_LEN(key_password),
					      (void *) key_password);

		if (err) {
			gnutls_assert();
			ret = tss_err_key(err);
			goto out_key_policy;
		}
	} else if (ret < 0) {
		gnutls_assert();
		goto out_session;
	}

	return 0;
      out_key_policy:
	Tspi_Context_CloseObject(s->tpm_ctx, s->tpm_key_policy);
	s->tpm_key_policy = 0;
      out_key:
	Tspi_Context_CloseObject(s->tpm_ctx, s->tpm_key);
	s->tpm_key = 0;
      out_session:
	tpm_close_session(s);
      out_ctx:
	gnutls_free(s);
	return ret;
}
Exemplo n.º 5
0
/**
 * gnutls_tpm_privkey_generate:
 * @pk: the public key algorithm
 * @bits: the security bits
 * @srk_password: a password to protect the exported key (optional)
 * @key_password: the password for the TPM (optional)
 * @format: the format of the private key
 * @pub_format: the format of the public key
 * @privkey: the generated key
 * @pubkey: the corresponding public key (may be null)
 * @flags: should be a list of GNUTLS_TPM_* flags
 *
 * This function will generate a private key in the TPM
 * chip. The private key will be generated within the chip
 * and will be exported in a wrapped with TPM's master key
 * form. Furthermore the wrapped key can be protected with
 * the provided @password.
 *
 * Note that bits in TPM is quantized value. If the input value
 * is not one of the allowed values, then it will be quantized to
 * one of 512, 1024, 2048, 4096, 8192 and 16384.
 *
 * Allowed flags are:
 *
 * %GNUTLS_TPM_KEY_SIGNING: Generate a signing key instead of a legacy,

 * %GNUTLS_TPM_REGISTER_KEY: Register the generate key in TPM. In that
 * case @privkey would contain a URL with the UUID.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.1.0
 **/
int
gnutls_tpm_privkey_generate(gnutls_pk_algorithm_t pk, unsigned int bits,
			    const char *srk_password,
			    const char *key_password,
			    gnutls_tpmkey_fmt_t format,
			    gnutls_x509_crt_fmt_t pub_format,
			    gnutls_datum_t * privkey,
			    gnutls_datum_t * pubkey, unsigned int flags)
{
	TSS_FLAG tpm_flags = TSS_KEY_VOLATILE;
	TSS_HKEY key_ctx;
	TSS_RESULT tssret;
	int ret;
	void *tdata;
	UINT32 tint;
	gnutls_datum_t tmpkey = { NULL, 0 };
	TSS_HPOLICY key_policy;
	gnutls_pubkey_t pub;
	struct tpm_ctx_st s;
	TSS_FLAG storage_type;
	TSS_HTPM htpm;
	uint8_t buf[32];

	if (flags & GNUTLS_TPM_KEY_SIGNING)
		tpm_flags |= TSS_KEY_TYPE_SIGNING;
	else
		tpm_flags |= TSS_KEY_TYPE_LEGACY;

	if (flags & GNUTLS_TPM_KEY_USER)
		storage_type = TSS_PS_TYPE_USER;
	else
		storage_type = TSS_PS_TYPE_SYSTEM;

	if (bits <= 512)
		tpm_flags |= TSS_KEY_SIZE_512;
	else if (bits <= 1024)
		tpm_flags |= TSS_KEY_SIZE_1024;
	else if (bits <= 2048)
		tpm_flags |= TSS_KEY_SIZE_2048;
	else if (bits <= 4096)
		tpm_flags |= TSS_KEY_SIZE_4096;
	else if (bits <= 8192)
		tpm_flags |= TSS_KEY_SIZE_8192;
	else
		tpm_flags |= TSS_KEY_SIZE_16384;

	ret = tpm_open_session(&s, srk_password);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* put some randomness into TPM. 
	 * Let's not trust it completely.
	 */
	tssret = Tspi_Context_GetTpmObject(s.tpm_ctx, &htpm);
	if (tssret != 0) {
		gnutls_assert();
		ret = tss_err(tssret);
		goto err_cc;
	}


	ret = _gnutls_rnd(GNUTLS_RND_RANDOM, buf, sizeof(buf));
	if (ret < 0) {
		gnutls_assert();
		goto err_cc;
	}

	tssret = Tspi_TPM_StirRandom(htpm, sizeof(buf), buf);
	if (tssret) {
		gnutls_assert();
	}

	tssret =
	    Tspi_Context_CreateObject(s.tpm_ctx, TSS_OBJECT_TYPE_RSAKEY,
				      tpm_flags, &key_ctx);
	if (tssret != 0) {
		gnutls_assert();
		ret = tss_err(tssret);
		goto err_cc;
	}

	tssret =
	    Tspi_SetAttribUint32(key_ctx, TSS_TSPATTRIB_KEY_INFO,
				 TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
				 TSS_SS_RSASSAPKCS1V15_DER);
	if (tssret != 0) {
		gnutls_assert();
		ret = tss_err(tssret);
		goto err_sa;
	}

	/* set the password of the actual key */
	if (key_password) {
		tssret =
		    Tspi_GetPolicyObject(key_ctx, TSS_POLICY_USAGE,
					 &key_policy);
		if (tssret != 0) {
			gnutls_assert();
			ret = tss_err(tssret);
			goto err_sa;
		}

		tssret = myTspi_Policy_SetSecret(key_policy,
						 SAFE_LEN(key_password),
						 (void *) key_password);
		if (tssret != 0) {
			gnutls_assert();
			ret = tss_err(tssret);
			goto err_sa;
		}
	}

	tssret = Tspi_Key_CreateKey(key_ctx, s.srk, 0);
	if (tssret != 0) {
		gnutls_assert();
		ret = tss_err(tssret);
		goto err_sa;
	}

	if (flags & GNUTLS_TPM_REGISTER_KEY) {
		TSS_UUID key_uuid;

		ret = randomize_uuid(&key_uuid);
		if (ret < 0) {
			gnutls_assert();
			goto err_sa;
		}

		tssret =
		    Tspi_Context_RegisterKey(s.tpm_ctx, key_ctx,
					     storage_type, key_uuid,
					     TSS_PS_TYPE_SYSTEM, srk_uuid);
		if (tssret != 0) {
			gnutls_assert();
			ret = tss_err(tssret);
			goto err_sa;
		}

		ret =
		    encode_tpmkey_url((char **) &privkey->data, &key_uuid,
				      storage_type);
		if (ret < 0) {
			TSS_HKEY tkey;

			Tspi_Context_UnregisterKey(s.tpm_ctx, storage_type,
						   key_uuid, &tkey);
			gnutls_assert();
			goto err_sa;
		}
		privkey->size = strlen((char *) privkey->data);

	} else {		/* get the key as blob */


		tssret =
		    Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_KEY_BLOB,
				       TSS_TSPATTRIB_KEYBLOB_BLOB, &tint,
				       (void *) &tdata);
		if (tssret != 0) {
			gnutls_assert();
			ret = tss_err(tssret);
			goto err_sa;
		}


		if (format == GNUTLS_TPMKEY_FMT_CTK_PEM) {
			ret =
			    _gnutls_x509_encode_string
			    (ASN1_ETYPE_OCTET_STRING, tdata, tint,
			     &tmpkey);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			ret =
			    _gnutls_fbase64_encode("TSS KEY BLOB",
						   tmpkey.data,
						   tmpkey.size, privkey);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
		} else {
			UINT32 tint2;

			tmpkey.size = tint + 32;	/* spec says no more than 20 */
			tmpkey.data = gnutls_malloc(tmpkey.size);
			if (tmpkey.data == NULL) {
				gnutls_assert();
				ret = GNUTLS_E_MEMORY_ERROR;
				goto cleanup;
			}

			tint2 = tmpkey.size;
			tssret =
			    Tspi_EncodeDER_TssBlob(tint, tdata,
						   TSS_BLOB_TYPE_PRIVATEKEY,
						   &tint2, tmpkey.data);
			if (tssret != 0) {
				gnutls_assert();
				ret = tss_err(tssret);
				goto cleanup;
			}

			tmpkey.size = tint2;

			privkey->data = tmpkey.data;
			privkey->size = tmpkey.size;
			tmpkey.data = NULL;
		}
	}

	/* read the public key */
	if (pubkey != NULL) {
		size_t psize;

		ret = gnutls_pubkey_init(&pub);
		if (ret < 0) {
			gnutls_assert();
			goto privkey_cleanup;
		}

		ret = read_pubkey(pub, key_ctx, &psize);
		if (ret < 0) {
			gnutls_assert();
			goto privkey_cleanup;
		}
		psize += 512;

		pubkey->data = gnutls_malloc(psize);
		if (pubkey->data == NULL) {
			gnutls_assert();
			ret = GNUTLS_E_MEMORY_ERROR;
			goto pubkey_cleanup;
		}

		ret =
		    gnutls_pubkey_export(pub, pub_format, pubkey->data,
					 &psize);
		if (ret < 0) {
			gnutls_assert();
			goto pubkey_cleanup;
		}
		pubkey->size = psize;

		gnutls_pubkey_deinit(pub);
	}

	ret = 0;
	goto cleanup;

      pubkey_cleanup:
	gnutls_pubkey_deinit(pub);
      privkey_cleanup:
	gnutls_free(privkey->data);
	privkey->data = NULL;
      cleanup:
	gnutls_free(tmpkey.data);
	tmpkey.data = NULL;
      err_sa:
	Tspi_Context_CloseObject(s.tpm_ctx, key_ctx);
      err_cc:
	tpm_close_session(&s);
	return ret;
}
Exemplo n.º 6
0
Arquivo: tpm.c Projeto: gnutls/gnutls
static int
import_tpm_key(gnutls_privkey_t pkey,
	       const gnutls_datum_t * fdata,
	       gnutls_tpmkey_fmt_t format,
	       TSS_UUID * uuid,
	       TSS_FLAG storage,
	       const char *srk_password, const char *_key_password)
{
	int err, ret;
	struct tpm_ctx_st *s;
	gnutls_datum_t tmp_sig;
	char *key_password = NULL;
	uint32_t authusage;

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

	if (_key_password != NULL) {
		gnutls_datum_t pout;
		ret = _gnutls_utf8_password_normalize(_key_password, strlen(_key_password), &pout, 1);
		if (ret < 0) {
			gnutls_assert();
			goto out_ctx;
		}
		key_password = (char*)pout.data;
	}

	/* normalization of srk_password happens in tpm_open_session() */

	ret = tpm_open_session(s, srk_password, 1);
	if (ret < 0) {
		gnutls_assert();
		goto out_ctx;
	}

	if (fdata != NULL) {
		ret =
		    load_key(s->tpm_ctx, s->srk, fdata, format,
			     &s->tpm_key);
		if (ret < 0) {
			gnutls_assert();
			goto out_session;
		}
	} else if (uuid) {
		err =
		    pTspi_Context_LoadKeyByUUID(s->tpm_ctx, storage,
					       *uuid, &s->tpm_key);

		if (err) {
			gnutls_assert();
			ret = tss_err(err);
			goto out_session;
		}
	} else {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		goto out_session;
	}

	err = pTspi_GetAttribUint32(s->tpm_key, TSS_TSPATTRIB_KEY_INFO,
				    TSS_TSPATTRIB_KEYINFO_AUTHUSAGE,
				    &authusage);
	if (err) {
		gnutls_assert();
		ret = tss_err(err);
		goto out_session;
	}

	if (authusage) {
		if (!_key_password) {
			ret = GNUTLS_E_TPM_KEY_PASSWORD_ERROR;
			goto out_session;
		}

		err = pTspi_Context_CreateObject(s->tpm_ctx,
						 TSS_OBJECT_TYPE_POLICY,
						 TSS_POLICY_USAGE,
						 &s->tpm_key_policy);
		if (err) {
			gnutls_assert();
			ret = tss_err(err);
			goto out_key;
		}

		err = pTspi_Policy_AssignToObject(s->tpm_key_policy,
						       s->tpm_key);
		if (err) {
			gnutls_assert();
			ret = tss_err(err);
			goto out_key_policy;
		}

		err = myTspi_Policy_SetSecret(s->tpm_key_policy,
					      SAFE_LEN(key_password),
					      (void *) key_password);

		if (err) {
			gnutls_assert();
			ret = tss_err_key(err);
			goto out_key_policy;
		}
	}

	ret =
	    gnutls_privkey_import_ext2(pkey, GNUTLS_PK_RSA, s,
				       tpm_sign_fn, NULL, tpm_deinit_fn,
				       0);
	if (ret < 0) {
		gnutls_assert();
		goto out_session;
	}

	ret =
	    gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA1, 0, &nulldata,
				     &tmp_sig);
	if (ret < 0) {
		gnutls_assert();
		goto out_session;
	}

	gnutls_free(key_password);

	return 0;
      out_key_policy:
	pTspi_Context_CloseObject(s->tpm_ctx, s->tpm_key_policy);
	s->tpm_key_policy = 0;
      out_key:
	pTspi_Context_CloseObject(s->tpm_ctx, s->tpm_key);
	s->tpm_key = 0;
      out_session:
	_gnutls_privkey_cleanup(pkey);
	tpm_close_session(s);
      out_ctx:
	gnutls_free(s);
	gnutls_free(key_password);
	return ret;
}