/** * 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; }
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; }
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; }
/** * 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; }
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; }