From: Nikos Mavrogiannopoulos Date: Fri, 13 Jul 2012 11:12:05 +0000 (+0200) Subject: small fixes in TPM support X-Git-Tag: gnutls_3_1_0pre0~75 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=27d773ad0cda6cd20ea191fb5d0bb511e794d410;p=thirdparty%2Fgnutls.git small fixes in TPM support --- diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index 19f824bb58..d41ef2c863 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -288,6 +288,10 @@ static const gnutls_error_entry error_algorithms[] = { ERROR_ENTRY (N_("TPM error."), GNUTLS_E_TPM_ERROR, 1), + ERROR_ENTRY (N_("TPM is not initialized."), + GNUTLS_E_TPM_UNINITIALIZED, 1), + ERROR_ENTRY (N_("TPM key was not found in persistent storage."), + GNUTLS_E_TPM_KEY_NOT_FOUND, 1), ERROR_ENTRY (N_("Cannot initialize a session with the TPM."), GNUTLS_E_TPM_SESSION_ERROR, 1), ERROR_ENTRY (N_("PKCS #11 error."), diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c index 0d6d087f8d..5c40b9ca57 100644 --- a/lib/gnutls_str.c +++ b/lib/gnutls_str.c @@ -207,10 +207,17 @@ _gnutls_buffer_resize (gnutls_buffer_st * dest, size_t new_size) } } +/* Appends the provided string. The null termination byte is appended + * but not included in length. + */ int _gnutls_buffer_append_str (gnutls_buffer_st * dest, const char *src) { - return _gnutls_buffer_append_data (dest, src, strlen (src)); +int ret; + ret = _gnutls_buffer_append_data (dest, src, strlen (src) + 1); + if (ret >= 0) dest->length--; + + return ret; } /* returns data from a string in a constant buffer. diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 21363f3a49..ea1db6e1a2 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1918,6 +1918,8 @@ int gnutls_load_file(const char* filename, gnutls_datum_t * data); #define GNUTLS_E_TPM_KEY_PASSWORD_ERROR -330 #define GNUTLS_E_TPM_SRK_PASSWORD_ERROR -331 #define GNUTLS_E_TPM_SESSION_ERROR -332 +#define GNUTLS_E_TPM_KEY_NOT_FOUND -333 +#define GNUTLS_E_TPM_UNINITIALIZED -334 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250 diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 1315ee7e4e..dd9aa1dd2a 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -813,6 +813,7 @@ GNUTLS_3_1_0 { gnutls_tpm_key_list_get_url; gnutls_tpm_get_registered; gnutls_tpm_privkey_delete; + gnutls_pubkey_import_tpm_url; } GNUTLS_3_0_0; GNUTLS_PRIVATE { diff --git a/lib/tpm.c b/lib/tpm.c index 27f720f646..d72b2f33ac 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -73,23 +73,43 @@ static int import_tpm_key (gnutls_privkey_t pkey, */ -static int tss_err(TSS_RESULT err) +static int tss_err_pwd(TSS_RESULT err, int pwd_error) { _gnutls_debug_log("TPM error: %s (%x)\n", Trspi_Error_String(err), (unsigned int)Trspi_Error_Code(err)); - switch(Trspi_Error_Code(err)) + + switch(ERROR_LAYER(err)) { - case TSS_E_COMM_FAILURE: - case TSS_E_NO_CONNECTION: - case TSS_E_CONNECTION_FAILED: - case TSS_E_CONNECTION_BROKEN: - return GNUTLS_E_TPM_SESSION_ERROR; - case TPM_E_AUTHFAIL: - return GNUTLS_E_TPM_SRK_PASSWORD_ERROR; - default: - return GNUTLS_E_TPM_ERROR; + case TSS_LAYER_TPM: + switch(ERROR_CODE(err)) + { + case TPM_E_AUTHFAIL: + return pwd_error; + case TPM_E_NOSRK: + return GNUTLS_E_TPM_UNINITIALIZED; + default: + return GNUTLS_E_TPM_ERROR; + } + case TSS_LAYER_TCS: + switch(ERROR_CODE(err)) + { + case TSS_E_COMM_FAILURE: + case TSS_E_NO_CONNECTION: + case TSS_E_CONNECTION_FAILED: + case TSS_E_CONNECTION_BROKEN: + return GNUTLS_E_TPM_SESSION_ERROR; + case TSS_E_PS_KEY_NOTFOUND: + return GNUTLS_E_TPM_KEY_NOT_FOUND; + default: + return GNUTLS_E_TPM_ERROR; + } + default: + return GNUTLS_E_TPM_ERROR; } } +#define tss_err(x) tss_err_pwd(x, GNUTLS_E_TPM_SRK_PASSWORD_ERROR) +#define tss_err_key(x) tss_err_pwd(x, GNUTLS_E_TPM_KEY_PASSWORD_ERROR) + static void tpm_deinit_fn (gnutls_privkey_t key, void *_s) { @@ -367,7 +387,7 @@ import_tpm_key (gnutls_privkey_t pkey, gnutls_assert (); _gnutls_debug_log ("Failed to set key PIN: %s\n", Trspi_Error_String (err)); - ret = GNUTLS_E_TPM_KEY_PASSWORD_ERROR; + ret = tss_err_key(err); goto out_key_policy; } } @@ -505,23 +525,86 @@ static int randomize_uuid(TSS_UUID* uuid) return 0; } -static int encode_tpmkey_url(char** url, TSS_UUID* uuid) +static int encode_tpmkey_url(char** url, const TSS_UUID* uuid, const TSS_UUID* parent) { -size_t size = UUID_SIZE*2+4+32; +size_t size = (UUID_SIZE*2+4)*2+32; +uint8_t u1[UUID_SIZE]; +gnutls_buffer_st buf; +gnutls_datum_t dret; +int ret; *url = gnutls_malloc(size); if (*url == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - snprintf(*url, size, "tpmkey:uuid=%.8x-%.4x-%.4x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x", - (unsigned int)uuid->ulTimeLow, (unsigned int)uuid->usTimeMid, - (unsigned int)uuid->usTimeHigh, (unsigned int)uuid->bClockSeqHigh, - (unsigned int)uuid->bClockSeqLow, (unsigned int)uuid->rgbNode[0], - (unsigned int)uuid->rgbNode[1], (unsigned int)uuid->rgbNode[2], - (unsigned int)uuid->rgbNode[3], (unsigned int)uuid->rgbNode[4], - (unsigned int)uuid->rgbNode[5]); + _gnutls_buffer_init(&buf); + + memcpy(u1, &uuid->ulTimeLow, 4); + memcpy(&u1[4], &uuid->usTimeMid, 2); + memcpy(&u1[6], &uuid->usTimeHigh, 2); + u1[8] = uuid->bClockSeqHigh; + u1[9] = uuid->bClockSeqLow; + memcpy(&u1[10], uuid->rgbNode, 6); + + ret = _gnutls_buffer_append_str(&buf, "tpmkey:uuid="); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_buffer_append_printf(&buf, "%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x", + (unsigned int)u1[0], (unsigned int)u1[1], (unsigned int)u1[2], (unsigned int)u1[3], + (unsigned int)u1[4], (unsigned int)u1[5], (unsigned int)u1[6], (unsigned int)u1[7], + (unsigned int)u1[8], (unsigned int)u1[9], (unsigned int)u1[10], (unsigned int)u1[11], + (unsigned int)u1[12], (unsigned int)u1[13], (unsigned int)u1[14], (unsigned int)u1[15]); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } + + if (parent) + { + memcpy(u1, &parent->ulTimeLow, 4); + memcpy(&u1[4], &parent->usTimeMid, 2); + memcpy(&u1[6], &parent->usTimeHigh, 2); + u1[8] = parent->bClockSeqHigh; + u1[9] = parent->bClockSeqLow; + memcpy(&u1[10], parent->rgbNode, 6); + + ret = _gnutls_buffer_append_str(&buf, ";parent="); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } + + ret = _gnutls_buffer_append_printf(&buf, "%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x", + (unsigned int)u1[0], (unsigned int)u1[1], (unsigned int)u1[2], (unsigned int)u1[3], + (unsigned int)u1[4], (unsigned int)u1[5], (unsigned int)u1[6], (unsigned int)u1[7], + (unsigned int)u1[8], (unsigned int)u1[9], (unsigned int)u1[10], (unsigned int)u1[11], + (unsigned int)u1[12], (unsigned int)u1[13], (unsigned int)u1[14], (unsigned int)u1[15]); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } + } + + ret = _gnutls_buffer_to_datum(&buf, &dret); + if (ret < 0) + { + gnutls_assert(); + goto cleanup; + } + + *url = (char*)dret.data; return 0; +cleanup: + _gnutls_buffer_clear(&buf); + return ret; } static int decode_tpmkey_url(const char* url, struct tpmkey_url_st *s) @@ -551,9 +634,6 @@ static int decode_tpmkey_url(const char* url, struct tpmkey_url_st *s) gnutls_assert(); goto cleanup; } - - - } else if ((p = strstr(url, "uuid=")) != NULL) { @@ -998,7 +1078,7 @@ struct tpm_ctx_st s; goto err_sa; } - /* set the key of the actual key */ + /* set the password of the actual key */ if (key_password) { tssret = Tspi_GetPolicyObject(key_ctx, TSS_POLICY_USAGE, &key_policy); @@ -1038,7 +1118,7 @@ struct tpm_ctx_st s; goto err_sa; } - tssret = Tspi_Context_RegisterKey(s.tpm_ctx, key_ctx, TSS_PS_TYPE_USER, + tssret = Tspi_Context_RegisterKey(s.tpm_ctx, key_ctx, TSS_PS_TYPE_SYSTEM, key_uuid, TSS_PS_TYPE_SYSTEM, srk_uuid); if (tssret != 0) { @@ -1047,12 +1127,12 @@ struct tpm_ctx_st s; goto err_sa; } - ret = encode_tpmkey_url((char**)&privkey->data, &key_uuid); + ret = encode_tpmkey_url((char**)&privkey->data, &key_uuid, &srk_uuid); if (ret < 0) { TSS_HKEY tkey; - Tspi_Context_UnregisterKey(s.tpm_ctx, TSS_PS_TYPE_USER, key_uuid, &tkey); + Tspi_Context_UnregisterKey(s.tpm_ctx, TSS_PS_TYPE_SYSTEM, key_uuid, &tkey); gnutls_assert(); goto err_sa; } @@ -1190,7 +1270,7 @@ gnutls_tpm_key_list_get_url (gnutls_tpm_key_list_t list, unsigned int idx, char* if (idx >= list->size) return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - return encode_tpmkey_url(url, &list->ki[idx].keyUUID); + return encode_tpmkey_url(url, &list->ki[idx].keyUUID, &list->ki[idx].parentKeyUUID); } /** @@ -1282,7 +1362,7 @@ int ret; if (ret < 0) return gnutls_assert_val(ret); - tssret = Tspi_Context_UnregisterKey(s.tpm_ctx, TSS_PS_TYPE_USER, durl.uuid, &tkey); + tssret = Tspi_Context_UnregisterKey(s.tpm_ctx, TSS_PS_TYPE_SYSTEM, durl.uuid, &tkey); if (tssret != 0) { gnutls_assert();