certtool is able to set certificate policies via a template
[gnutls.git] / lib / tpm.c
blobd1d74ce0ad00982b77d36c1418b757c270b5985b
1 /*
2 * OpenConnect (SSL + DTLS) VPN client
4 * Copyright © 2012 Free Software Foundation.
5 * Copyright © 2008-2012 Intel Corporation.
7 * Author: David Woodhouse <dwmw2@infradead.org>
8 * Author: Nikos Mavrogiannopoulos
10 * GnuTLS is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 3 of
13 * the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>
26 * TPM code based on client-tpm.c from
27 * Carolin Latze <latze@angry-red-pla.net> and Tobias Soder
30 #include <gnutls/gnutls.h>
31 #include <gnutls/abstract.h>
32 #include <gnutls/tpm.h>
34 #include <gnutls_int.h>
35 #include <gnutls_errors.h>
36 #include <pkcs11_int.h>
37 #include <x509/common.h>
38 #include <x509_b64.h>
39 #include <random.h>
40 #include <pin.h>
42 #include <trousers/tss.h>
43 #include <trousers/trousers.h>
45 struct tpm_ctx_st
47 TSS_HCONTEXT tpm_ctx;
48 TSS_HKEY tpm_key;
49 TSS_HPOLICY tpm_key_policy;
50 TSS_HKEY srk;
51 TSS_HPOLICY srk_policy;
54 struct tpm_key_list_st
56 UINT32 size;
57 TSS_KM_KEYINFO2 * ki;
58 TSS_HCONTEXT tpm_ctx;
61 static void tpm_close_session(struct tpm_ctx_st *s);
62 static int import_tpm_key (gnutls_privkey_t pkey,
63 const gnutls_datum_t * fdata,
64 gnutls_tpmkey_fmt_t format,
65 TSS_UUID *uuid,
66 TSS_FLAG storage_type,
67 const char *srk_password,
68 const char *key_password);
69 static int encode_tpmkey_url(char** url, const TSS_UUID* uuid, TSS_FLAG storage);
71 /* TPM URL format:
73 * tpmkey:file=/path/to/file
74 * tpmkey:uuid=7f468c16-cb7f-11e1-824d-b3a4f4b20343;storage=user
75 * tpmkey:uuid=7f468c16-cb7f-11e1-824d-b3a4f4b20343;storage=system
80 static int tss_err_pwd(TSS_RESULT err, int pwd_error)
82 _gnutls_debug_log("TPM (%s) error: %s (%x)\n", Trspi_Error_Layer(err), Trspi_Error_String(err), (unsigned int)Trspi_Error_Code(err));
84 switch(ERROR_LAYER(err))
86 case TSS_LAYER_TPM:
87 switch(ERROR_CODE(err))
89 case TPM_E_AUTHFAIL:
90 return pwd_error;
91 case TPM_E_NOSRK:
92 return GNUTLS_E_TPM_UNINITIALIZED;
93 default:
94 return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
96 case TSS_LAYER_TCS:
97 case TSS_LAYER_TSP:
98 switch(ERROR_CODE(err))
100 case TSS_E_COMM_FAILURE:
101 case TSS_E_NO_CONNECTION:
102 case TSS_E_CONNECTION_FAILED:
103 case TSS_E_CONNECTION_BROKEN:
104 return GNUTLS_E_TPM_SESSION_ERROR;
105 case TSS_E_PS_KEY_NOTFOUND:
106 return GNUTLS_E_TPM_KEY_NOT_FOUND;
107 default:
108 return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
110 default:
111 return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
115 #define tss_err(x) tss_err_pwd(x, GNUTLS_E_TPM_SRK_PASSWORD_ERROR)
116 #define tss_err_key(x) tss_err_pwd(x, GNUTLS_E_TPM_KEY_PASSWORD_ERROR)
118 static void
119 tpm_deinit_fn (gnutls_privkey_t key, void *_s)
121 struct tpm_ctx_st *s = _s;
123 Tspi_Context_CloseObject (s->tpm_ctx, s->tpm_key_policy);
124 Tspi_Context_CloseObject (s->tpm_ctx, s->tpm_key);
126 tpm_close_session(s);
127 gnutls_free (s);
130 static int
131 tpm_sign_fn (gnutls_privkey_t key, void *_s,
132 const gnutls_datum_t * data, gnutls_datum_t * sig)
134 struct tpm_ctx_st *s = _s;
135 TSS_HHASH hash;
136 int err;
138 _gnutls_debug_log ("TPM sign function called for %u bytes.\n",
139 data->size);
141 err =
142 Tspi_Context_CreateObject (s->tpm_ctx,
143 TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER,
144 &hash);
145 if (err)
147 gnutls_assert ();
148 _gnutls_debug_log ("Failed to create TPM hash object: %s\n",
149 Trspi_Error_String (err));
150 return GNUTLS_E_PK_SIGN_FAILED;
152 err = Tspi_Hash_SetHashValue (hash, data->size, data->data);
153 if (err)
155 gnutls_assert ();
156 _gnutls_debug_log ("Failed to set value in TPM hash object: %s\n",
157 Trspi_Error_String (err));
158 Tspi_Context_CloseObject (s->tpm_ctx, hash);
159 return GNUTLS_E_PK_SIGN_FAILED;
161 err = Tspi_Hash_Sign (hash, s->tpm_key, &sig->size, &sig->data);
162 Tspi_Context_CloseObject (s->tpm_ctx, hash);
163 if (err)
165 if (s->tpm_key_policy || err != TPM_E_AUTHFAIL)
166 _gnutls_debug_log ("TPM hash signature failed: %s\n",
167 Trspi_Error_String (err));
168 if (err == TPM_E_AUTHFAIL)
169 return GNUTLS_E_TPM_KEY_PASSWORD_ERROR;
170 else
171 return GNUTLS_E_PK_SIGN_FAILED;
173 return 0;
176 static const unsigned char nullpass[20];
177 static const gnutls_datum_t nulldata = {(void*)nullpass, 20};
178 const TSS_UUID srk_uuid = TSS_UUID_SRK;
180 static int tpm_pin(struct pin_info_st* pin_info, const TSS_UUID* uuid, TSS_FLAG storage,
181 char* pin, unsigned int pin_size, unsigned int attempts)
183 unsigned int flags = 0;
184 const char* label;
185 char* url = NULL;
186 int ret;
188 if (attempts > 0)
189 flags |= GNUTLS_PIN_WRONG;
191 if (uuid)
193 if (memcmp(uuid, &srk_uuid, sizeof(TSS_UUID)) == 0)
194 label = "SRK";
195 else
197 ret = encode_tpmkey_url(&url, uuid, storage);
198 if (ret < 0)
199 return gnutls_assert_val(ret);
201 label = url;
204 else
205 label = "unknown";
207 if (pin_info && pin_info->cb)
208 ret = pin_info->cb(pin_info->data, attempts, "TPM", label, flags, pin, pin_size);
209 else if (_gnutls_pin_func)
210 ret = _gnutls_pin_func(_gnutls_pin_data, attempts, "TPM", label, flags, pin, pin_size);
211 else
212 ret = gnutls_assert_val(GNUTLS_E_TPM_KEY_PASSWORD_ERROR); /* doesn't really matter */
214 if (ret < 0)
216 gnutls_assert();
217 goto cleanup;
220 ret = 0;
221 cleanup:
222 gnutls_free(url);
223 return ret;
227 static TSS_RESULT myTspi_Policy_SetSecret(TSS_HPOLICY hPolicy,
228 UINT32 ulSecretLength, BYTE* rgbSecret)
230 if (rgbSecret == NULL)
232 /* Well known NULL key */
233 return Tspi_Policy_SetSecret (hPolicy,
234 TSS_SECRET_MODE_SHA1,
235 sizeof (nullpass), (BYTE *) nullpass);
237 else /* key is given */
239 return Tspi_Policy_SetSecret (hPolicy, TSS_SECRET_MODE_PLAIN,
240 ulSecretLength, rgbSecret);
244 #define SAFE_LEN(x) (x==NULL?0:strlen(x))
246 static int tpm_open_session(struct tpm_ctx_st *s, const char* srk_password)
248 int err, ret;
250 err = Tspi_Context_Create (&s->tpm_ctx);
251 if (err)
253 gnutls_assert ();
254 return tss_err(err);
257 err = Tspi_Context_Connect (s->tpm_ctx, NULL);
258 if (err)
260 gnutls_assert ();
261 ret = tss_err(err);
262 goto out_tspi_ctx;
265 err =
266 Tspi_Context_LoadKeyByUUID (s->tpm_ctx, TSS_PS_TYPE_SYSTEM,
267 srk_uuid, &s->srk);
268 if (err)
270 gnutls_assert ();
271 ret = tss_err(err);
272 goto out_tspi_ctx;
275 err = Tspi_GetPolicyObject (s->srk, TSS_POLICY_USAGE, &s->srk_policy);
276 if (err)
278 gnutls_assert ();
279 ret = tss_err(err);
280 goto out_srk;
283 err = myTspi_Policy_SetSecret (s->srk_policy,
284 SAFE_LEN (srk_password), (BYTE *) srk_password);
285 if (err)
287 gnutls_assert ();
288 ret = tss_err(err);
289 goto out_srkpol;
292 return 0;
294 out_srkpol:
295 Tspi_Context_CloseObject (s->tpm_ctx, s->srk_policy);
296 s->srk_policy = 0;
297 out_srk:
298 Tspi_Context_CloseObject (s->tpm_ctx, s->srk);
299 s->srk = 0;
300 out_tspi_ctx:
301 Tspi_Context_Close (s->tpm_ctx);
302 s->tpm_ctx = 0;
303 return ret;
307 static void tpm_close_session(struct tpm_ctx_st *s)
309 Tspi_Context_CloseObject (s->tpm_ctx, s->srk_policy);
310 s->srk_policy = 0;
311 Tspi_Context_CloseObject (s->tpm_ctx, s->srk);
312 s->srk = 0;
313 Tspi_Context_Close (s->tpm_ctx);
314 s->tpm_ctx = 0;
317 static int
318 import_tpm_key_cb (gnutls_privkey_t pkey, const gnutls_datum_t * fdata,
319 gnutls_tpmkey_fmt_t format, TSS_UUID *uuid,
320 TSS_FLAG storage, const char *srk_password,
321 const char *key_password)
323 unsigned int attempts = 0;
324 char pin1[GNUTLS_PKCS11_MAX_PIN_LEN];
325 char pin2[GNUTLS_PKCS11_MAX_PIN_LEN];
326 int ret, ret2;
330 ret = import_tpm_key(pkey, fdata, format, uuid, storage, srk_password, key_password);
332 if (attempts > 3)
333 break;
335 if (ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR)
337 ret2 = tpm_pin(&pkey->pin, &srk_uuid, storage, pin1, sizeof(pin1), attempts++);
338 if (ret2 < 0)
340 gnutls_assert();
341 return GNUTLS_E_TPM_SRK_PASSWORD_ERROR;
343 srk_password = pin1;
346 if (ret == GNUTLS_E_TPM_KEY_PASSWORD_ERROR)
348 ret2 = tpm_pin(&pkey->pin, uuid, storage, pin2, sizeof(pin2), attempts++);
349 if (ret2 < 0)
351 gnutls_assert();
352 return GNUTLS_E_TPM_KEY_PASSWORD_ERROR;
354 key_password = pin2;
357 while(ret == GNUTLS_E_TPM_KEY_PASSWORD_ERROR || ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR);
359 if (ret < 0)
360 gnutls_assert();
361 return ret;
364 static int load_key(TSS_HCONTEXT tpm_ctx, TSS_HKEY srk,
365 const gnutls_datum_t * fdata, gnutls_tpmkey_fmt_t format,
366 TSS_HKEY* tpm_key)
368 int ret, err;
369 gnutls_datum_t asn1 = { NULL, 0 };
371 if (format == GNUTLS_TPMKEY_FMT_CTK_PEM)
373 gnutls_datum_t td;
375 ret = gnutls_pem_base64_decode_alloc ("TSS KEY BLOB", fdata, &asn1);
376 if (ret)
378 gnutls_assert ();
379 _gnutls_debug_log ("Error decoding TSS key blob: %s\n",
380 gnutls_strerror (ret));
381 return ret;
384 ret = _gnutls_x509_decode_string(NULL, asn1.data, asn1.size, &td);
385 if (ret < 0)
387 gnutls_assert();
388 goto cleanup;
390 gnutls_free(asn1.data);
391 asn1.data = td.data;
392 asn1.size = td.size;
394 else /* DER */
396 UINT32 tint2;
397 UINT32 type;
399 asn1.size = fdata->size;
400 asn1.data = gnutls_malloc(asn1.size);
401 if (asn1.data == NULL)
403 gnutls_assert();
404 return GNUTLS_E_MEMORY_ERROR;
407 tint2 = asn1.size;
408 err = Tspi_DecodeBER_TssBlob(fdata->size, fdata->data, &type,
409 &tint2, asn1.data);
410 if (err != 0)
412 gnutls_assert();
413 ret = tss_err(err);
414 goto cleanup;
417 asn1.size = tint2;
420 /* ... we get it here instead. */
421 err = Tspi_Context_LoadKeyByBlob (tpm_ctx, srk,
422 asn1.size, asn1.data, tpm_key);
423 if (err != 0)
425 gnutls_assert ();
426 ret = tss_err(err);
427 goto cleanup;
430 ret = 0;
432 cleanup:
433 gnutls_free (asn1.data);
435 return ret;
439 static int
440 import_tpm_key (gnutls_privkey_t pkey,
441 const gnutls_datum_t * fdata,
442 gnutls_tpmkey_fmt_t format,
443 TSS_UUID *uuid,
444 TSS_FLAG storage,
445 const char *srk_password,
446 const char *key_password)
448 int err, ret;
449 struct tpm_ctx_st *s;
450 gnutls_datum_t tmp_sig;
452 s = gnutls_malloc (sizeof (*s));
453 if (s == NULL)
455 gnutls_assert ();
456 return GNUTLS_E_MEMORY_ERROR;
459 ret = tpm_open_session(s, srk_password);
460 if (ret < 0)
462 gnutls_assert();
463 goto out_ctx;
466 if (fdata != NULL)
468 ret = load_key(s->tpm_ctx, s->srk, fdata, format, &s->tpm_key);
469 if (ret < 0)
471 gnutls_assert();
472 goto out_session;
475 else if (uuid)
477 err =
478 Tspi_Context_LoadKeyByUUID (s->tpm_ctx, storage,
479 *uuid, &s->tpm_key);
481 if (err)
483 gnutls_assert ();
484 ret = tss_err(err);
485 goto out_session;
488 else
490 gnutls_assert();
491 ret = GNUTLS_E_INVALID_REQUEST;
492 goto out_session;
495 ret =
496 gnutls_privkey_import_ext2 (pkey, GNUTLS_PK_RSA, s,
497 tpm_sign_fn, NULL, tpm_deinit_fn, 0);
498 if (ret < 0)
500 gnutls_assert ();
501 goto out_session;
504 ret =
505 gnutls_privkey_sign_data (pkey, GNUTLS_DIG_SHA1, 0, &nulldata, &tmp_sig);
506 if (ret == GNUTLS_E_TPM_KEY_PASSWORD_ERROR)
508 if (!s->tpm_key_policy)
510 err = Tspi_Context_CreateObject (s->tpm_ctx,
511 TSS_OBJECT_TYPE_POLICY,
512 TSS_POLICY_USAGE,
513 &s->tpm_key_policy);
514 if (err)
516 gnutls_assert ();
517 ret = tss_err(err);
518 goto out_key;
521 err = Tspi_Policy_AssignToObject (s->tpm_key_policy, s->tpm_key);
522 if (err)
524 gnutls_assert ();
525 ret = tss_err(err);
526 goto out_key_policy;
530 err = myTspi_Policy_SetSecret (s->tpm_key_policy,
531 SAFE_LEN(key_password), (void *) key_password);
533 if (err)
535 gnutls_assert ();
536 ret = tss_err_key(err);
537 goto out_key_policy;
540 else if (ret < 0)
542 gnutls_assert ();
543 goto out_session;
546 return 0;
547 out_key_policy:
548 Tspi_Context_CloseObject (s->tpm_ctx, s->tpm_key_policy);
549 s->tpm_key_policy = 0;
550 out_key:
551 Tspi_Context_CloseObject (s->tpm_ctx, s->tpm_key);
552 s->tpm_key = 0;
553 out_session:
554 tpm_close_session(s);
555 out_ctx:
556 gnutls_free (s);
557 return ret;
561 * gnutls_privkey_import_tpm_raw:
562 * @pkey: The private key
563 * @fdata: The TPM key to be imported
564 * @format: The format of the private key
565 * @srk_password: The password for the SRK key (optional)
566 * @key_password: A password for the key (optional)
567 * @flags: should be zero
569 * This function will import the given private key to the abstract
570 * #gnutls_privkey_t structure.
572 * With respect to passwords the same as in gnutls_privkey_import_tpm_url() apply.
574 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
575 * negative error value.
577 * Since: 3.1.0
581 gnutls_privkey_import_tpm_raw (gnutls_privkey_t pkey,
582 const gnutls_datum_t * fdata,
583 gnutls_tpmkey_fmt_t format,
584 const char *srk_password,
585 const char *key_password,
586 unsigned int flags)
588 if (flags & GNUTLS_PRIVKEY_DISABLE_CALLBACKS)
589 return import_tpm_key(pkey, fdata, format, NULL, 0, srk_password, key_password);
590 else
591 return import_tpm_key_cb(pkey, fdata, format, NULL, 0, srk_password, key_password);
594 struct tpmkey_url_st
596 char* filename;
597 TSS_UUID uuid;
598 TSS_FLAG storage;
599 unsigned int uuid_set;
602 static void clear_tpmkey_url(struct tpmkey_url_st *s)
604 gnutls_free(s->filename);
605 memset(s, 0, sizeof(*s));
608 static int
609 unescape_string (char *output, const char *input, size_t * size,
610 char terminator)
612 gnutls_buffer_st str;
613 int ret = 0;
614 char *p;
615 int len;
617 _gnutls_buffer_init (&str);
619 /* find terminator */
620 p = strchr (input, terminator);
621 if (p != NULL)
622 len = p - input;
623 else
624 len = strlen (input);
626 ret = _gnutls_buffer_append_data (&str, input, len);
627 if (ret < 0)
629 gnutls_assert ();
630 return ret;
633 ret = _gnutls_buffer_unescape (&str);
634 if (ret < 0)
636 gnutls_assert ();
637 return ret;
640 ret = _gnutls_buffer_append_data (&str, "", 1);
641 if (ret < 0)
643 gnutls_assert ();
644 return ret;
647 _gnutls_buffer_pop_data (&str, output, size);
649 _gnutls_buffer_clear (&str);
651 return ret;
654 #define UUID_SIZE 16
656 static int randomize_uuid(TSS_UUID* uuid)
658 uint8_t raw_uuid[16];
659 int ret;
661 ret = _gnutls_rnd (GNUTLS_RND_NONCE, raw_uuid, sizeof(raw_uuid));
662 if (ret < 0)
663 return gnutls_assert_val(ret);
665 /* mark it as random uuid */
666 raw_uuid[6] &= 0x0f;
667 raw_uuid[6] |= 0x40;
668 raw_uuid[8] &= 0x0f;
669 raw_uuid[8] |= 0x80;
671 memcpy(&uuid->ulTimeLow, raw_uuid, 4);
672 memcpy(&uuid->usTimeMid, &raw_uuid[4], 2);
673 memcpy(&uuid->usTimeHigh, &raw_uuid[6], 2);
674 uuid->bClockSeqHigh = raw_uuid[8];
675 uuid->bClockSeqLow = raw_uuid[9];
676 memcpy(&uuid->rgbNode, &raw_uuid[10], 6);
678 return 0;
681 static int encode_tpmkey_url(char** url, const TSS_UUID* uuid, TSS_FLAG storage)
683 size_t size = (UUID_SIZE*2+4)*2+32;
684 uint8_t u1[UUID_SIZE];
685 gnutls_buffer_st buf;
686 gnutls_datum_t dret;
687 int ret;
689 *url = gnutls_malloc(size);
690 if (*url == NULL)
691 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
693 _gnutls_buffer_init(&buf);
695 memcpy(u1, &uuid->ulTimeLow, 4);
696 memcpy(&u1[4], &uuid->usTimeMid, 2);
697 memcpy(&u1[6], &uuid->usTimeHigh, 2);
698 u1[8] = uuid->bClockSeqHigh;
699 u1[9] = uuid->bClockSeqLow;
700 memcpy(&u1[10], uuid->rgbNode, 6);
702 ret = _gnutls_buffer_append_str(&buf, "tpmkey:uuid=");
703 if (ret < 0)
705 gnutls_assert();
706 goto cleanup;
709 ret = _gnutls_buffer_append_printf(&buf, "%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x",
710 (unsigned int)u1[0], (unsigned int)u1[1], (unsigned int)u1[2], (unsigned int)u1[3],
711 (unsigned int)u1[4], (unsigned int)u1[5], (unsigned int)u1[6], (unsigned int)u1[7],
712 (unsigned int)u1[8], (unsigned int)u1[9], (unsigned int)u1[10], (unsigned int)u1[11],
713 (unsigned int)u1[12], (unsigned int)u1[13], (unsigned int)u1[14], (unsigned int)u1[15]);
714 if (ret < 0)
716 gnutls_assert();
717 goto cleanup;
720 ret = _gnutls_buffer_append_printf(&buf, ";storage=%s", (storage==TSS_PS_TYPE_USER)?"user":"system");
721 if (ret < 0)
723 gnutls_assert();
724 goto cleanup;
727 ret = _gnutls_buffer_to_datum(&buf, &dret);
728 if (ret < 0)
730 gnutls_assert();
731 goto cleanup;
734 *url = (char*)dret.data;
736 return 0;
737 cleanup:
738 _gnutls_buffer_clear(&buf);
739 return ret;
742 static int decode_tpmkey_url(const char* url, struct tpmkey_url_st *s)
744 char* p;
745 size_t size;
746 int ret;
747 unsigned int i, j;
749 if (strstr (url, "tpmkey:") == NULL)
750 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
752 memset(s, 0, sizeof(*s));
754 p = strstr(url, "file=");
755 if (p != NULL)
757 p += sizeof ("file=") - 1;
758 size = strlen(p);
759 s->filename = gnutls_malloc(size+1);
760 if (s->filename == NULL)
761 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
763 ret = unescape_string (s->filename, p, &size, ';');
764 if (ret < 0)
766 gnutls_assert();
767 goto cleanup;
769 s->filename[size] = 0;
771 else if ((p = strstr(url, "uuid=")) != NULL)
773 char tmp_uuid[33];
774 uint8_t raw_uuid[16];
776 p += sizeof ("uuid=") - 1;
777 size = strlen(p);
779 for (j=i=0;i<size;i++)
781 if (j==sizeof(tmp_uuid)-1)
783 break;
785 if (isalnum(p[i])) tmp_uuid[j++]=p[i];
787 tmp_uuid[j] = 0;
789 size = sizeof(raw_uuid);
790 ret = _gnutls_hex2bin(tmp_uuid, strlen(tmp_uuid), raw_uuid, &size);
791 if (ret < 0)
793 gnutls_assert();
794 goto cleanup;
797 memcpy(&s->uuid.ulTimeLow, raw_uuid, 4);
798 memcpy(&s->uuid.usTimeMid, &raw_uuid[4], 2);
799 memcpy(&s->uuid.usTimeHigh, &raw_uuid[6], 2);
800 s->uuid.bClockSeqHigh = raw_uuid[8];
801 s->uuid.bClockSeqLow = raw_uuid[9];
802 memcpy(&s->uuid.rgbNode, &raw_uuid[10], 6);
803 s->uuid_set = 1;
805 else
807 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
810 if ((p = strstr(url, "storage=user")) != NULL)
811 s->storage = TSS_PS_TYPE_USER;
812 else
813 s->storage = TSS_PS_TYPE_SYSTEM;
815 return 0;
817 cleanup:
818 clear_tpmkey_url(s);
819 return ret;
823 * gnutls_privkey_import_tpm_url:
824 * @pkey: The private key
825 * @url: The URL of the TPM key to be imported
826 * @srk_password: The password for the SRK key (optional)
827 * @key_password: A password for the key (optional)
828 * @flags: One of the GNUTLS_PRIVKEY_* flags
830 * This function will import the given private key to the abstract
831 * #gnutls_privkey_t structure.
833 * Note that unless %GNUTLS_PRIVKEY_DISABLE_CALLBACKS
834 * is specified, if incorrect (or NULL) passwords are given
835 * the PKCS11 callback functions will be used to obtain the
836 * correct passwords. Otherwise if the SRK password is wrong
837 * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned and if the key password
838 * is wrong or not provided then %GNUTLS_E_TPM_KEY_PASSWORD_ERROR
839 * is returned.
841 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
842 * negative error value.
844 * Since: 3.1.0
848 gnutls_privkey_import_tpm_url (gnutls_privkey_t pkey,
849 const char* url,
850 const char *srk_password,
851 const char *key_password,
852 unsigned int flags)
854 struct tpmkey_url_st durl;
855 gnutls_datum_t fdata = { NULL, 0 };
856 int ret;
858 ret = decode_tpmkey_url(url, &durl);
859 if (ret < 0)
860 return gnutls_assert_val(ret);
862 if (durl.filename)
864 ret = gnutls_load_file(durl.filename, &fdata);
865 if (ret < 0)
867 gnutls_assert();
868 _gnutls_debug_log("Error loading %s\n", durl.filename);
869 goto cleanup;
872 ret = gnutls_privkey_import_tpm_raw (pkey, &fdata, GNUTLS_TPMKEY_FMT_CTK_PEM,
873 srk_password, key_password, flags);
874 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
875 ret = gnutls_privkey_import_tpm_raw (pkey, &fdata, GNUTLS_TPMKEY_FMT_DER,
876 srk_password, key_password, flags);
878 if (ret < 0)
880 gnutls_assert();
881 goto cleanup;
884 else if (durl.uuid_set)
886 if (flags & GNUTLS_PRIVKEY_DISABLE_CALLBACKS)
887 ret = import_tpm_key (pkey, NULL, 0, &durl.uuid, durl.storage, srk_password, key_password);
888 else
889 ret = import_tpm_key_cb (pkey, NULL, 0, &durl.uuid, durl.storage, srk_password, key_password);
890 if (ret < 0)
892 gnutls_assert();
893 goto cleanup;
897 ret = 0;
898 cleanup:
899 gnutls_free(fdata.data);
900 clear_tpmkey_url(&durl);
901 return ret;
905 /* reads the RSA public key from the given TSS key.
906 * If psize is non-null it contains the total size of the parameters
907 * in bytes */
908 static int read_pubkey(gnutls_pubkey_t pub, TSS_HKEY key_ctx, size_t *psize)
910 void* tdata;
911 UINT32 tint;
912 TSS_RESULT tssret;
913 gnutls_datum_t m, e;
914 int ret;
916 /* read the public key */
918 tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
919 TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &tint, (void*)&tdata);
920 if (tssret != 0)
922 gnutls_assert();
923 return tss_err(tssret);
926 m.data = tdata;
927 m.size = tint;
929 tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
930 TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT, &tint, (void*)&tdata);
931 if (tssret != 0)
933 gnutls_assert();
934 Tspi_Context_FreeMemory(key_ctx, m.data);
935 return tss_err(tssret);
938 e.data = tdata;
939 e.size = tint;
941 ret = gnutls_pubkey_import_rsa_raw(pub, &m, &e);
943 Tspi_Context_FreeMemory(key_ctx, m.data);
944 Tspi_Context_FreeMemory(key_ctx, e.data);
946 if (ret < 0)
947 return gnutls_assert_val(ret);
949 if (psize)
950 *psize = e.size + m.size;
952 return 0;
957 static int
958 import_tpm_pubkey (gnutls_pubkey_t pkey,
959 const gnutls_datum_t * fdata,
960 gnutls_tpmkey_fmt_t format,
961 TSS_UUID *uuid,
962 TSS_FLAG storage,
963 const char *srk_password)
965 int err, ret;
966 struct tpm_ctx_st s;
968 ret = tpm_open_session(&s, srk_password);
969 if (ret < 0)
970 return gnutls_assert_val(ret);
972 if (fdata != NULL)
974 ret = load_key(s.tpm_ctx, s.srk, fdata, format, &s.tpm_key);
975 if (ret < 0)
977 gnutls_assert();
978 goto out_session;
981 else if (uuid)
983 err =
984 Tspi_Context_LoadKeyByUUID (s.tpm_ctx, storage,
985 *uuid, &s.tpm_key);
986 if (err)
988 gnutls_assert ();
989 ret = tss_err(err);
990 goto out_session;
993 else
995 gnutls_assert();
996 ret = GNUTLS_E_INVALID_REQUEST;
997 goto out_session;
1000 ret = read_pubkey(pkey, s.tpm_key, NULL);
1001 if (ret < 0)
1003 gnutls_assert();
1004 goto out_session;
1007 ret = 0;
1008 out_session:
1009 tpm_close_session(&s);
1010 return ret;
1013 static int
1014 import_tpm_pubkey_cb (gnutls_pubkey_t pkey,
1015 const gnutls_datum_t * fdata,
1016 gnutls_tpmkey_fmt_t format,
1017 TSS_UUID *uuid,
1018 TSS_FLAG storage,
1019 const char *srk_password)
1021 unsigned int attempts = 0;
1022 char pin1[GNUTLS_PKCS11_MAX_PIN_LEN];
1023 int ret;
1027 ret = import_tpm_pubkey(pkey, fdata, format, uuid, storage, srk_password);
1029 if (attempts > 3)
1030 break;
1032 if (ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR)
1034 ret = tpm_pin(&pkey->pin, &srk_uuid, storage, pin1, sizeof(pin1), attempts++);
1035 if (ret < 0)
1037 gnutls_assert();
1038 return GNUTLS_E_TPM_SRK_PASSWORD_ERROR;
1040 srk_password = pin1;
1043 while(ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR);
1045 if (ret < 0)
1046 gnutls_assert();
1047 return ret;
1052 * gnutls_pubkey_import_tpm_raw:
1053 * @pkey: The public key
1054 * @fdata: The TPM key to be imported
1055 * @format: The format of the private key
1056 * @srk_password: The password for the SRK key (optional)
1057 * @flags: One of the GNUTLS_PUBKEY_* flags
1059 * This function will import the public key from the provided TPM key
1060 * structure.
1062 * With respect to passwords the same as in
1063 * gnutls_pubkey_import_tpm_url() apply.
1065 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1066 * negative error value.
1068 * Since: 3.1.0
1071 gnutls_pubkey_import_tpm_raw (gnutls_pubkey_t pkey,
1072 const gnutls_datum_t * fdata,
1073 gnutls_tpmkey_fmt_t format,
1074 const char *srk_password,
1075 unsigned int flags)
1077 if (flags & GNUTLS_PUBKEY_DISABLE_CALLBACKS)
1078 return import_tpm_pubkey_cb(pkey, fdata, format, NULL, 0, srk_password);
1079 else
1080 return import_tpm_pubkey(pkey, fdata, format, NULL, 0, srk_password);
1084 * gnutls_pubkey_import_tpm_url:
1085 * @pkey: The public key
1086 * @url: The URL of the TPM key to be imported
1087 * @srk_password: The password for the SRK key (optional)
1088 * @flags: should be zero
1090 * This function will import the given private key to the abstract
1091 * #gnutls_privkey_t structure.
1093 * Note that unless %GNUTLS_PUBKEY_DISABLE_CALLBACKS
1094 * is specified, if incorrect (or NULL) passwords are given
1095 * the PKCS11 callback functions will be used to obtain the
1096 * correct passwords. Otherwise if the SRK password is wrong
1097 * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned.
1099 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1100 * negative error value.
1102 * Since: 3.1.0
1106 gnutls_pubkey_import_tpm_url (gnutls_pubkey_t pkey,
1107 const char* url,
1108 const char *srk_password,
1109 unsigned int flags)
1111 struct tpmkey_url_st durl;
1112 gnutls_datum_t fdata = { NULL, 0 };
1113 int ret;
1115 ret = decode_tpmkey_url(url, &durl);
1116 if (ret < 0)
1117 return gnutls_assert_val(ret);
1119 if (durl.filename)
1122 ret = gnutls_load_file(durl.filename, &fdata);
1123 if (ret < 0)
1125 gnutls_assert();
1126 goto cleanup;
1129 ret = gnutls_pubkey_import_tpm_raw (pkey, &fdata, GNUTLS_TPMKEY_FMT_CTK_PEM,
1130 srk_password, flags);
1131 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1132 ret = gnutls_pubkey_import_tpm_raw (pkey, &fdata, GNUTLS_TPMKEY_FMT_DER,
1133 srk_password, flags);
1134 if (ret < 0)
1136 gnutls_assert();
1137 goto cleanup;
1140 else if (durl.uuid_set)
1142 if (flags & GNUTLS_PUBKEY_DISABLE_CALLBACKS)
1143 ret = import_tpm_pubkey (pkey, NULL, 0, &durl.uuid, durl.storage, srk_password);
1144 else
1145 ret = import_tpm_pubkey_cb (pkey, NULL, 0, &durl.uuid, durl.storage, srk_password);
1146 if (ret < 0)
1148 gnutls_assert();
1149 goto cleanup;
1153 ret = 0;
1154 cleanup:
1155 gnutls_free(fdata.data);
1156 clear_tpmkey_url(&durl);
1157 return ret;
1162 * gnutls_tpm_privkey_generate:
1163 * @pk: the public key algorithm
1164 * @bits: the security bits
1165 * @srk_password: a password to protect the exported key (optional)
1166 * @key_password: the password for the TPM (optional)
1167 * @format: the format of the private key
1168 * @pub_format: the format of the public key
1169 * @privkey: the generated key
1170 * @pubkey: the corresponding public key (may be null)
1171 * @flags: should be a list of GNUTLS_TPM_* flags
1173 * This function will generate a private key in the TPM
1174 * chip. The private key will be generated within the chip
1175 * and will be exported in a wrapped with TPM's master key
1176 * form. Furthermore the wrapped key can be protected with
1177 * the provided @password.
1179 * Note that bits in TPM is quantized value. If the input value
1180 * is not one of the allowed values, then it will be quantized to
1181 * one of 512, 1024, 2048, 4096, 8192 and 16384.
1183 * Allowed flags are:
1185 * %GNUTLS_TPM_KEY_SIGNING: Generate a signing key instead of a legacy,
1187 * %GNUTLS_TPM_REGISTER_KEY: Register the generate key in TPM. In that
1188 * case @privkey would contain a URL with the UUID.
1190 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1191 * negative error value.
1193 * Since: 3.1.0
1196 gnutls_tpm_privkey_generate (gnutls_pk_algorithm_t pk, unsigned int bits,
1197 const char* srk_password,
1198 const char* key_password,
1199 gnutls_tpmkey_fmt_t format,
1200 gnutls_x509_crt_fmt_t pub_format,
1201 gnutls_datum_t* privkey,
1202 gnutls_datum_t* pubkey,
1203 unsigned int flags)
1205 TSS_FLAG tpm_flags = TSS_KEY_VOLATILE;
1206 TSS_HKEY key_ctx;
1207 TSS_RESULT tssret;
1208 int ret;
1209 void* tdata;
1210 UINT32 tint;
1211 gnutls_datum_t tmpkey = {NULL, 0};
1212 TSS_HPOLICY key_policy;
1213 gnutls_pubkey_t pub;
1214 struct tpm_ctx_st s;
1215 TSS_FLAG storage_type;
1216 TSS_HTPM htpm;
1217 uint8_t buf[32];
1219 if (flags & GNUTLS_TPM_KEY_SIGNING)
1220 tpm_flags |= TSS_KEY_TYPE_SIGNING;
1221 else
1222 tpm_flags |= TSS_KEY_TYPE_LEGACY;
1224 if (flags & GNUTLS_TPM_KEY_USER)
1225 storage_type = TSS_PS_TYPE_USER;
1226 else
1227 storage_type = TSS_PS_TYPE_SYSTEM;
1229 if (bits <= 512)
1230 tpm_flags |= TSS_KEY_SIZE_512;
1231 else if (bits <= 1024)
1232 tpm_flags |= TSS_KEY_SIZE_1024;
1233 else if (bits <= 2048)
1234 tpm_flags |= TSS_KEY_SIZE_2048;
1235 else if (bits <= 4096)
1236 tpm_flags |= TSS_KEY_SIZE_4096;
1237 else if (bits <= 8192)
1238 tpm_flags |= TSS_KEY_SIZE_8192;
1239 else
1240 tpm_flags |= TSS_KEY_SIZE_16384;
1242 ret = tpm_open_session(&s, srk_password);
1243 if (ret < 0)
1244 return gnutls_assert_val(ret);
1246 /* put some randomness into TPM.
1247 * Let's not trust it completely.
1249 tssret = Tspi_Context_GetTpmObject(s.tpm_ctx, &htpm);
1250 if (tssret != 0)
1252 gnutls_assert();
1253 ret = tss_err(tssret);
1254 goto err_cc;
1258 ret = _gnutls_rnd(GNUTLS_RND_RANDOM, buf, sizeof(buf));
1259 if (ret < 0)
1261 gnutls_assert();
1262 goto err_cc;
1265 tssret = Tspi_TPM_StirRandom(htpm, sizeof(buf), buf);
1266 if (tssret)
1268 gnutls_assert();
1271 tssret = Tspi_Context_CreateObject(s.tpm_ctx, TSS_OBJECT_TYPE_RSAKEY, tpm_flags, &key_ctx);
1272 if (tssret != 0)
1274 gnutls_assert();
1275 ret = tss_err(tssret);
1276 goto err_cc;
1279 tssret = Tspi_SetAttribUint32(key_ctx, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
1280 TSS_SS_RSASSAPKCS1V15_DER);
1281 if (tssret != 0)
1283 gnutls_assert();
1284 ret = tss_err(tssret);
1285 goto err_sa;
1288 /* set the password of the actual key */
1289 if (key_password)
1291 tssret = Tspi_GetPolicyObject(key_ctx, TSS_POLICY_USAGE, &key_policy);
1292 if (tssret != 0)
1294 gnutls_assert();
1295 ret = tss_err(tssret);
1296 goto err_sa;
1299 tssret = myTspi_Policy_SetSecret(key_policy,
1300 SAFE_LEN(key_password), (void*)key_password);
1301 if (tssret != 0)
1303 gnutls_assert();
1304 ret = tss_err(tssret);
1305 goto err_sa;
1309 tssret = Tspi_Key_CreateKey(key_ctx, s.srk, 0);
1310 if (tssret != 0)
1312 gnutls_assert();
1313 ret = tss_err(tssret);
1314 goto err_sa;
1317 if (flags & GNUTLS_TPM_REGISTER_KEY)
1319 TSS_UUID key_uuid;
1321 ret = randomize_uuid(&key_uuid);
1322 if (ret < 0)
1324 gnutls_assert();
1325 goto err_sa;
1328 tssret = Tspi_Context_RegisterKey(s.tpm_ctx, key_ctx, storage_type,
1329 key_uuid, TSS_PS_TYPE_SYSTEM, srk_uuid);
1330 if (tssret != 0)
1332 gnutls_assert();
1333 ret = tss_err(tssret);
1334 goto err_sa;
1337 ret = encode_tpmkey_url((char**)&privkey->data, &key_uuid, storage_type);
1338 if (ret < 0)
1340 TSS_HKEY tkey;
1342 Tspi_Context_UnregisterKey(s.tpm_ctx, storage_type, key_uuid, &tkey);
1343 gnutls_assert();
1344 goto err_sa;
1346 privkey->size = strlen((char*)privkey->data);
1349 else /* get the key as blob */
1352 tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_KEY_BLOB,
1353 TSS_TSPATTRIB_KEYBLOB_BLOB, &tint, (void*)&tdata);
1354 if (tssret != 0)
1356 gnutls_assert();
1357 ret = tss_err(tssret);
1358 goto err_sa;
1362 if (format == GNUTLS_TPMKEY_FMT_CTK_PEM)
1364 ret = _gnutls_x509_encode_string(NULL, tdata, tint, &tmpkey);
1365 if (ret < 0)
1367 gnutls_assert();
1368 goto cleanup;
1371 ret = _gnutls_fbase64_encode ("TSS KEY BLOB", tmpkey.data, tmpkey.size, privkey);
1372 if (ret < 0)
1374 gnutls_assert();
1375 goto cleanup;
1378 else
1380 UINT32 tint2;
1382 tmpkey.size = tint + 32; /* spec says no more than 20 */
1383 tmpkey.data = gnutls_malloc(tmpkey.size);
1384 if (tmpkey.data == NULL)
1386 gnutls_assert();
1387 ret = GNUTLS_E_MEMORY_ERROR;
1388 goto cleanup;
1391 tint2 = tmpkey.size;
1392 tssret = Tspi_EncodeDER_TssBlob(tint, tdata, TSS_BLOB_TYPE_PRIVATEKEY,
1393 &tint2, tmpkey.data);
1394 if (tssret != 0)
1396 gnutls_assert();
1397 ret = tss_err(tssret);
1398 goto cleanup;
1401 tmpkey.size = tint2;
1403 privkey->data = tmpkey.data;
1404 privkey->size = tmpkey.size;
1405 tmpkey.data = NULL;
1409 /* read the public key */
1410 if (pubkey != NULL)
1412 size_t psize;
1414 ret = gnutls_pubkey_init(&pub);
1415 if (ret < 0)
1417 gnutls_assert();
1418 goto privkey_cleanup;
1421 ret = read_pubkey(pub, key_ctx, &psize);
1422 if (ret < 0)
1424 gnutls_assert();
1425 goto privkey_cleanup;
1427 psize+=512;
1429 pubkey->data = gnutls_malloc(psize);
1430 if (pubkey->data == NULL)
1432 gnutls_assert();
1433 ret = GNUTLS_E_MEMORY_ERROR;
1434 goto pubkey_cleanup;
1437 ret = gnutls_pubkey_export(pub, pub_format, pubkey->data, &psize);
1438 if (ret < 0)
1440 gnutls_assert();
1441 goto pubkey_cleanup;
1443 pubkey->size = psize;
1445 gnutls_pubkey_deinit(pub);
1448 ret = 0;
1449 goto cleanup;
1451 pubkey_cleanup:
1452 gnutls_pubkey_deinit(pub);
1453 privkey_cleanup:
1454 gnutls_free(privkey->data);
1455 privkey->data = NULL;
1456 cleanup:
1457 gnutls_free(tmpkey.data);
1458 tmpkey.data = NULL;
1459 err_sa:
1460 Tspi_Context_CloseObject(s.tpm_ctx, key_ctx);
1461 err_cc:
1462 tpm_close_session(&s);
1463 return ret;
1468 * gnutls_tpm_key_list_deinit:
1469 * @list: a list of the keys
1471 * This function will deinitialize the list of stored keys in the TPM.
1473 * Since: 3.1.0
1475 void
1476 gnutls_tpm_key_list_deinit (gnutls_tpm_key_list_t list)
1478 if (list->tpm_ctx != 0) Tspi_Context_Close (list->tpm_ctx);
1479 gnutls_free(list);
1483 * gnutls_tpm_key_list_get_url:
1484 * @list: a list of the keys
1485 * @idx: The index of the key (starting from zero)
1486 * @url: The URL to be returned
1487 * @flags: should be zero
1489 * This function will return for each given index a URL of
1490 * the corresponding key.
1491 * If the provided index is out of bounds then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1492 * is returned.
1494 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1495 * negative error value.
1497 * Since: 3.1.0
1500 gnutls_tpm_key_list_get_url (gnutls_tpm_key_list_t list, unsigned int idx, char** url, unsigned int flags)
1502 if (idx >= list->size)
1503 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1505 return encode_tpmkey_url(url, &list->ki[idx].keyUUID, list->ki[idx].persistentStorageType);
1509 * gnutls_tpm_get_registered:
1510 * @list: a list to store the keys
1512 * This function will get a list of stored keys in the TPM. The uuid
1513 * of those keys
1515 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1516 * negative error value.
1518 * Since: 3.1.0
1521 gnutls_tpm_get_registered (gnutls_tpm_key_list_t *list)
1523 TSS_RESULT tssret;
1524 int ret;
1526 *list = gnutls_calloc(1, sizeof(struct tpm_key_list_st));
1527 if (*list == NULL)
1528 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1530 tssret = Tspi_Context_Create (&(*list)->tpm_ctx);
1531 if (tssret)
1533 gnutls_assert ();
1534 ret = tss_err(tssret);
1535 goto cleanup;
1538 tssret = Tspi_Context_Connect ((*list)->tpm_ctx, NULL);
1539 if (tssret)
1541 gnutls_assert ();
1542 ret = tss_err(tssret);
1543 goto cleanup;
1546 tssret =
1547 Tspi_Context_GetRegisteredKeysByUUID2((*list)->tpm_ctx, TSS_PS_TYPE_SYSTEM,
1548 NULL, &(*list)->size, &(*list)->ki);
1549 if (tssret)
1551 gnutls_assert ();
1552 ret = tss_err(tssret);
1553 goto cleanup;
1555 return 0;
1557 cleanup:
1558 gnutls_tpm_key_list_deinit(*list);
1560 return ret;
1564 * gnutls_tpm_privkey_delete:
1565 * @url: the URL describing the key
1566 * @srk_password: a password for the SRK key
1568 * This function will unregister the private key from the TPM
1569 * chip.
1571 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1572 * negative error value.
1574 * Since: 3.1.0
1577 gnutls_tpm_privkey_delete (const char* url, const char* srk_password)
1579 struct tpm_ctx_st s;
1580 struct tpmkey_url_st durl;
1581 TSS_RESULT tssret;
1582 TSS_HKEY tkey;
1583 int ret;
1585 ret = decode_tpmkey_url(url, &durl);
1586 if (ret < 0)
1587 return gnutls_assert_val(ret);
1589 if (durl.uuid_set == 0)
1590 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1592 ret = tpm_open_session(&s, srk_password);
1593 if (ret < 0)
1594 return gnutls_assert_val(ret);
1596 tssret = Tspi_Context_UnregisterKey(s.tpm_ctx, durl.storage, durl.uuid, &tkey);
1597 if (tssret != 0)
1599 gnutls_assert();
1600 ret = tss_err(tssret);
1601 goto err_cc;
1604 ret = 0;
1605 err_cc:
1606 tpm_close_session(&s);
1607 return ret;