summaryrefslogtreecommitdiff
path: root/lib/tpm.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2016-12-03 14:36:40 -0800
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-12-05 08:26:57 +0100
commitc0d9e58db9fe2836ca2b5cfe033dbe943d70cdb2 (patch)
tree1475b7f624cc28bd5cb6f775beb80e7acba21b11 /lib/tpm.c
parent49146f057d91fb5cad8bcdcf91a21fe9686f2305 (diff)
downloadgnutls-c0d9e58db9fe2836ca2b5cfe033dbe943d70cdb2.tar.gz
tpm: fix handling of keys requiring authorization
There are several problems with the key handling in the tpm code. The first, and most serious, is that we should make sure we understand the authorization requirements of a key *before* using it. The reason for this is that the TPM has a dictionary attack defence and is programmed to lock up after a certain number of authorization failures (which can be very small). If we try first without authorization, we may lock up the TPM. The fix for this is to check whether authorization is required and supply it before using the key. Secondly, if the key does require authorization but no password is supplied we should return immediately, since we know the TPM will give us an authorization error anyway. Thirdly, we should unconditionally read the policy of the key rather than checking if a policy exists: Policies are tied to key objects, so if there is an old policy in s->tpm_key_policy, but we're creating a new key, the key it belonged to will be closed, meaning the policy will be invalid. Fix this by always setting the policy each time we get a new key object. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'lib/tpm.c')
-rw-r--r--lib/tpm.c72
1 files changed, 44 insertions, 28 deletions
diff --git a/lib/tpm.c b/lib/tpm.c
index aac83186a0..1d63f83cb1 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -71,6 +71,7 @@ typedef TSS_RESULT (*Tspi_DecodeBER_TssBlob_func)(UINT32, BYTE*, UINT32*, UINT32
typedef TSS_RESULT (*Tspi_Context_LoadKeyByBlob_func)(TSS_HCONTEXT, TSS_HKEY, UINT32, BYTE*, TSS_HKEY*);
typedef TSS_RESULT (*Tspi_Policy_AssignToObject_func)(TSS_HPOLICY, TSS_HOBJECT);
typedef TSS_RESULT (*Tspi_GetAttribData_func)(TSS_HOBJECT, TSS_FLAG, TSS_FLAG, UINT32*, BYTE**);
+typedef TSS_RESULT (*Tspi_GetAttribUint32_func)(TSS_HOBJECT, TSS_FLAG, TSS_FLAG, UINT32*);
typedef TSS_RESULT (*Tspi_Context_GetTpmObject_func)(TSS_HCONTEXT, TSS_HTPM*);
typedef TSS_RESULT (*Tspi_TPM_StirRandom_func)(TSS_HTPM, UINT32, BYTE*);
typedef TSS_RESULT (*Tspi_SetAttribUint32_func)(TSS_HOBJECT, TSS_FLAG, TSS_FLAG, UINT32);
@@ -96,6 +97,7 @@ static Tspi_DecodeBER_TssBlob_func pTspi_DecodeBER_TssBlob;
static Tspi_Context_LoadKeyByBlob_func pTspi_Context_LoadKeyByBlob;
static Tspi_Policy_AssignToObject_func pTspi_Policy_AssignToObject;
static Tspi_GetAttribData_func pTspi_GetAttribData;
+static Tspi_GetAttribUint32_func pTspi_GetAttribUint32;
static Tspi_Context_GetTpmObject_func pTspi_Context_GetTpmObject;
static Tspi_TPM_StirRandom_func pTspi_TPM_StirRandom;
static Tspi_SetAttribUint32_func pTspi_SetAttribUint32;
@@ -144,6 +146,7 @@ static int check_init(void)
_DLSYM(tpm_dl,Tspi_Context_LoadKeyByBlob);
_DLSYM(tpm_dl,Tspi_Policy_AssignToObject);
_DLSYM(tpm_dl,Tspi_GetAttribData);
+ _DLSYM(tpm_dl,Tspi_GetAttribUint32);
_DLSYM(tpm_dl,Tspi_Context_GetTpmObject);
_DLSYM(tpm_dl,Tspi_TPM_StirRandom);
_DLSYM(tpm_dl,Tspi_SetAttribUint32);
@@ -580,6 +583,7 @@ import_tpm_key(gnutls_privkey_t pkey,
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) {
@@ -629,39 +633,37 @@ import_tpm_key(gnutls_privkey_t pkey,
goto out_session;
}
- ret =
- gnutls_privkey_import_ext2(pkey, GNUTLS_PK_RSA, s,
- tpm_sign_fn, NULL, tpm_deinit_fn,
- 0);
- if (ret < 0) {
+ 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;
}
- 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 = 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;
- }
+ 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,
+ err = pTspi_Policy_AssignToObject(s->tpm_key_policy,
s->tpm_key);
- if (err) {
- gnutls_assert();
- ret = tss_err(err);
- goto out_key_policy;
- }
+ if (err) {
+ gnutls_assert();
+ ret = tss_err(err);
+ goto out_key_policy;
}
err = myTspi_Policy_SetSecret(s->tpm_key_policy,
@@ -673,7 +675,21 @@ import_tpm_key(gnutls_privkey_t pkey,
ret = tss_err_key(err);
goto out_key_policy;
}
- } else if (ret < 0) {
+ }
+
+ 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;
}