Documented gnutls_certificate_verification_status_print().
[gnutls.git] / lib / tpm.c
blobe9c8123ae60af45c04e6a01c0c3a34ef6e8d28ec
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 };
370 size_t slen;
372 if (format == GNUTLS_TPMKEY_FMT_CTK_PEM)
374 ret = gnutls_pem_base64_decode_alloc ("TSS KEY BLOB", fdata, &asn1);
375 if (ret)
377 gnutls_assert ();
378 _gnutls_debug_log ("Error decoding TSS key blob: %s\n",
379 gnutls_strerror (ret));
380 return ret;
383 slen = asn1.size;
384 ret = _gnutls_x509_decode_octet_string(NULL, asn1.data, asn1.size, asn1.data, &slen);
385 if (ret < 0)
387 gnutls_assert();
388 goto cleanup;
390 asn1.size = slen;
392 else /* DER */
394 UINT32 tint2;
395 UINT32 type;
397 asn1.size = fdata->size;
398 asn1.data = gnutls_malloc(asn1.size);
399 if (asn1.data == NULL)
401 gnutls_assert();
402 return GNUTLS_E_MEMORY_ERROR;
405 tint2 = asn1.size;
406 err = Tspi_DecodeBER_TssBlob(fdata->size, fdata->data, &type,
407 &tint2, asn1.data);
408 if (err != 0)
410 gnutls_assert();
411 ret = tss_err(err);
412 goto cleanup;
415 asn1.size = tint2;
418 /* ... we get it here instead. */
419 err = Tspi_Context_LoadKeyByBlob (tpm_ctx, srk,
420 asn1.size, asn1.data, tpm_key);
421 if (err != 0)
423 gnutls_assert ();
424 ret = tss_err(err);
425 goto cleanup;
428 ret = 0;
430 cleanup:
431 gnutls_free (asn1.data);
433 return ret;
437 static int
438 import_tpm_key (gnutls_privkey_t pkey,
439 const gnutls_datum_t * fdata,
440 gnutls_tpmkey_fmt_t format,
441 TSS_UUID *uuid,
442 TSS_FLAG storage,
443 const char *srk_password,
444 const char *key_password)
446 int err, ret;
447 struct tpm_ctx_st *s;
448 gnutls_datum_t tmp_sig;
450 s = gnutls_malloc (sizeof (*s));
451 if (s == NULL)
453 gnutls_assert ();
454 return GNUTLS_E_MEMORY_ERROR;
457 ret = tpm_open_session(s, srk_password);
458 if (ret < 0)
460 gnutls_assert();
461 goto out_ctx;
464 if (fdata != NULL)
466 ret = load_key(s->tpm_ctx, s->srk, fdata, format, &s->tpm_key);
467 if (ret < 0)
469 gnutls_assert();
470 goto out_session;
473 else if (uuid)
475 err =
476 Tspi_Context_LoadKeyByUUID (s->tpm_ctx, storage,
477 *uuid, &s->tpm_key);
479 if (err)
481 gnutls_assert ();
482 ret = tss_err(err);
483 goto out_session;
486 else
488 gnutls_assert();
489 ret = GNUTLS_E_INVALID_REQUEST;
490 goto out_session;
493 ret =
494 gnutls_privkey_import_ext2 (pkey, GNUTLS_PK_RSA, s,
495 tpm_sign_fn, NULL, tpm_deinit_fn, 0);
496 if (ret < 0)
498 gnutls_assert ();
499 goto out_session;
502 ret =
503 gnutls_privkey_sign_data (pkey, GNUTLS_DIG_SHA1, 0, &nulldata, &tmp_sig);
504 if (ret == GNUTLS_E_TPM_KEY_PASSWORD_ERROR)
506 if (!s->tpm_key_policy)
508 err = Tspi_Context_CreateObject (s->tpm_ctx,
509 TSS_OBJECT_TYPE_POLICY,
510 TSS_POLICY_USAGE,
511 &s->tpm_key_policy);
512 if (err)
514 gnutls_assert ();
515 ret = tss_err(err);
516 goto out_key;
519 err = Tspi_Policy_AssignToObject (s->tpm_key_policy, s->tpm_key);
520 if (err)
522 gnutls_assert ();
523 ret = tss_err(err);
524 goto out_key_policy;
528 err = myTspi_Policy_SetSecret (s->tpm_key_policy,
529 SAFE_LEN(key_password), (void *) key_password);
531 if (err)
533 gnutls_assert ();
534 ret = tss_err_key(err);
535 goto out_key_policy;
538 else if (ret < 0)
540 gnutls_assert ();
541 goto out_session;
544 return 0;
545 out_key_policy:
546 Tspi_Context_CloseObject (s->tpm_ctx, s->tpm_key_policy);
547 s->tpm_key_policy = 0;
548 out_key:
549 Tspi_Context_CloseObject (s->tpm_ctx, s->tpm_key);
550 s->tpm_key = 0;
551 out_session:
552 tpm_close_session(s);
553 out_ctx:
554 gnutls_free (s);
555 return ret;
559 * gnutls_privkey_import_tpm_raw:
560 * @pkey: The private key
561 * @fdata: The TPM key to be imported
562 * @format: The format of the private key
563 * @srk_password: The password for the SRK key (optional)
564 * @key_password: A password for the key (optional)
565 * @flags: should be zero
567 * This function will import the given private key to the abstract
568 * #gnutls_privkey_t structure.
570 * With respect to passwords the same as in gnutls_privkey_import_tpm_url() apply.
572 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
573 * negative error value.
575 * Since: 3.1.0
579 gnutls_privkey_import_tpm_raw (gnutls_privkey_t pkey,
580 const gnutls_datum_t * fdata,
581 gnutls_tpmkey_fmt_t format,
582 const char *srk_password,
583 const char *key_password,
584 unsigned int flags)
586 if (flags & GNUTLS_PRIVKEY_DISABLE_CALLBACKS)
587 return import_tpm_key(pkey, fdata, format, NULL, 0, srk_password, key_password);
588 else
589 return import_tpm_key_cb(pkey, fdata, format, NULL, 0, srk_password, key_password);
592 struct tpmkey_url_st
594 char* filename;
595 TSS_UUID uuid;
596 TSS_FLAG storage;
597 unsigned int uuid_set;
600 static void clear_tpmkey_url(struct tpmkey_url_st *s)
602 gnutls_free(s->filename);
603 memset(s, 0, sizeof(*s));
606 static int
607 unescape_string (char *output, const char *input, size_t * size,
608 char terminator)
610 gnutls_buffer_st str;
611 int ret = 0;
612 char *p;
613 int len;
615 _gnutls_buffer_init (&str);
617 /* find terminator */
618 p = strchr (input, terminator);
619 if (p != NULL)
620 len = p - input;
621 else
622 len = strlen (input);
624 ret = _gnutls_buffer_append_data (&str, input, len);
625 if (ret < 0)
627 gnutls_assert ();
628 return ret;
631 ret = _gnutls_buffer_unescape (&str);
632 if (ret < 0)
634 gnutls_assert ();
635 return ret;
638 ret = _gnutls_buffer_append_data (&str, "", 1);
639 if (ret < 0)
641 gnutls_assert ();
642 return ret;
645 _gnutls_buffer_pop_data (&str, output, size);
647 _gnutls_buffer_clear (&str);
649 return ret;
652 #define UUID_SIZE 16
654 static int randomize_uuid(TSS_UUID* uuid)
656 uint8_t raw_uuid[16];
657 int ret;
659 ret = _gnutls_rnd (GNUTLS_RND_NONCE, raw_uuid, sizeof(raw_uuid));
660 if (ret < 0)
661 return gnutls_assert_val(ret);
663 /* mark it as random uuid */
664 raw_uuid[6] &= 0x0f;
665 raw_uuid[6] |= 0x40;
666 raw_uuid[8] &= 0x0f;
667 raw_uuid[8] |= 0x80;
669 memcpy(&uuid->ulTimeLow, raw_uuid, 4);
670 memcpy(&uuid->usTimeMid, &raw_uuid[4], 2);
671 memcpy(&uuid->usTimeHigh, &raw_uuid[6], 2);
672 uuid->bClockSeqHigh = raw_uuid[8];
673 uuid->bClockSeqLow = raw_uuid[9];
674 memcpy(&uuid->rgbNode, &raw_uuid[10], 6);
676 return 0;
679 static int encode_tpmkey_url(char** url, const TSS_UUID* uuid, TSS_FLAG storage)
681 size_t size = (UUID_SIZE*2+4)*2+32;
682 uint8_t u1[UUID_SIZE];
683 gnutls_buffer_st buf;
684 gnutls_datum_t dret;
685 int ret;
687 *url = gnutls_malloc(size);
688 if (*url == NULL)
689 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
691 _gnutls_buffer_init(&buf);
693 memcpy(u1, &uuid->ulTimeLow, 4);
694 memcpy(&u1[4], &uuid->usTimeMid, 2);
695 memcpy(&u1[6], &uuid->usTimeHigh, 2);
696 u1[8] = uuid->bClockSeqHigh;
697 u1[9] = uuid->bClockSeqLow;
698 memcpy(&u1[10], uuid->rgbNode, 6);
700 ret = _gnutls_buffer_append_str(&buf, "tpmkey:uuid=");
701 if (ret < 0)
703 gnutls_assert();
704 goto cleanup;
707 ret = _gnutls_buffer_append_printf(&buf, "%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x",
708 (unsigned int)u1[0], (unsigned int)u1[1], (unsigned int)u1[2], (unsigned int)u1[3],
709 (unsigned int)u1[4], (unsigned int)u1[5], (unsigned int)u1[6], (unsigned int)u1[7],
710 (unsigned int)u1[8], (unsigned int)u1[9], (unsigned int)u1[10], (unsigned int)u1[11],
711 (unsigned int)u1[12], (unsigned int)u1[13], (unsigned int)u1[14], (unsigned int)u1[15]);
712 if (ret < 0)
714 gnutls_assert();
715 goto cleanup;
718 ret = _gnutls_buffer_append_printf(&buf, ";storage=%s", (storage==TSS_PS_TYPE_USER)?"user":"system");
719 if (ret < 0)
721 gnutls_assert();
722 goto cleanup;
725 ret = _gnutls_buffer_to_datum(&buf, &dret);
726 if (ret < 0)
728 gnutls_assert();
729 goto cleanup;
732 *url = (char*)dret.data;
734 return 0;
735 cleanup:
736 _gnutls_buffer_clear(&buf);
737 return ret;
740 static int decode_tpmkey_url(const char* url, struct tpmkey_url_st *s)
742 char* p;
743 size_t size;
744 int ret;
745 unsigned int i, j;
747 if (strstr (url, "tpmkey:") == NULL)
748 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
750 memset(s, 0, sizeof(*s));
752 p = strstr(url, "file=");
753 if (p != NULL)
755 p += sizeof ("file=") - 1;
756 size = strlen(p);
757 s->filename = gnutls_malloc(size+1);
758 if (s->filename == NULL)
759 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
761 ret = unescape_string (s->filename, p, &size, ';');
762 if (ret < 0)
764 gnutls_assert();
765 goto cleanup;
767 s->filename[size] = 0;
769 else if ((p = strstr(url, "uuid=")) != NULL)
771 char tmp_uuid[33];
772 uint8_t raw_uuid[16];
774 p += sizeof ("uuid=") - 1;
775 size = strlen(p);
777 for (j=i=0;i<size;i++)
779 if (j==sizeof(tmp_uuid)-1)
781 break;
783 if (isalnum(p[i])) tmp_uuid[j++]=p[i];
785 tmp_uuid[j] = 0;
787 size = sizeof(raw_uuid);
788 ret = _gnutls_hex2bin(tmp_uuid, strlen(tmp_uuid), raw_uuid, &size);
789 if (ret < 0)
791 gnutls_assert();
792 goto cleanup;
795 memcpy(&s->uuid.ulTimeLow, raw_uuid, 4);
796 memcpy(&s->uuid.usTimeMid, &raw_uuid[4], 2);
797 memcpy(&s->uuid.usTimeHigh, &raw_uuid[6], 2);
798 s->uuid.bClockSeqHigh = raw_uuid[8];
799 s->uuid.bClockSeqLow = raw_uuid[9];
800 memcpy(&s->uuid.rgbNode, &raw_uuid[10], 6);
801 s->uuid_set = 1;
803 else
805 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
808 if ((p = strstr(url, "storage=user")) != NULL)
809 s->storage = TSS_PS_TYPE_USER;
810 else
811 s->storage = TSS_PS_TYPE_SYSTEM;
813 return 0;
815 cleanup:
816 clear_tpmkey_url(s);
817 return ret;
821 * gnutls_privkey_import_tpm_url:
822 * @pkey: The private key
823 * @url: The URL of the TPM key to be imported
824 * @srk_password: The password for the SRK key (optional)
825 * @key_password: A password for the key (optional)
826 * @flags: One of the GNUTLS_PRIVKEY_* flags
828 * This function will import the given private key to the abstract
829 * #gnutls_privkey_t structure.
831 * Note that unless %GNUTLS_PRIVKEY_DISABLE_CALLBACKS
832 * is specified, if incorrect (or NULL) passwords are given
833 * the PKCS11 callback functions will be used to obtain the
834 * correct passwords. Otherwise if the SRK password is wrong
835 * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned and if the key password
836 * is wrong or not provided then %GNUTLS_E_TPM_KEY_PASSWORD_ERROR
837 * is returned.
839 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
840 * negative error value.
842 * Since: 3.1.0
846 gnutls_privkey_import_tpm_url (gnutls_privkey_t pkey,
847 const char* url,
848 const char *srk_password,
849 const char *key_password,
850 unsigned int flags)
852 struct tpmkey_url_st durl;
853 gnutls_datum_t fdata = { NULL, 0 };
854 int ret;
856 ret = decode_tpmkey_url(url, &durl);
857 if (ret < 0)
858 return gnutls_assert_val(ret);
860 if (durl.filename)
862 ret = gnutls_load_file(durl.filename, &fdata);
863 if (ret < 0)
865 gnutls_assert();
866 _gnutls_debug_log("Error loading %s\n", durl.filename);
867 goto cleanup;
870 ret = gnutls_privkey_import_tpm_raw (pkey, &fdata, GNUTLS_TPMKEY_FMT_CTK_PEM,
871 srk_password, key_password, flags);
872 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
873 ret = gnutls_privkey_import_tpm_raw (pkey, &fdata, GNUTLS_TPMKEY_FMT_DER,
874 srk_password, key_password, flags);
876 if (ret < 0)
878 gnutls_assert();
879 goto cleanup;
882 else if (durl.uuid_set)
884 if (flags & GNUTLS_PRIVKEY_DISABLE_CALLBACKS)
885 ret = import_tpm_key (pkey, NULL, 0, &durl.uuid, durl.storage, srk_password, key_password);
886 else
887 ret = import_tpm_key_cb (pkey, NULL, 0, &durl.uuid, durl.storage, srk_password, key_password);
888 if (ret < 0)
890 gnutls_assert();
891 goto cleanup;
895 ret = 0;
896 cleanup:
897 gnutls_free(fdata.data);
898 clear_tpmkey_url(&durl);
899 return ret;
903 /* reads the RSA public key from the given TSS key.
904 * If psize is non-null it contains the total size of the parameters
905 * in bytes */
906 static int read_pubkey(gnutls_pubkey_t pub, TSS_HKEY key_ctx, size_t *psize)
908 void* tdata;
909 UINT32 tint;
910 TSS_RESULT tssret;
911 gnutls_datum_t m, e;
912 int ret;
914 /* read the public key */
916 tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
917 TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &tint, (void*)&tdata);
918 if (tssret != 0)
920 gnutls_assert();
921 return tss_err(tssret);
924 m.data = tdata;
925 m.size = tint;
927 tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
928 TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT, &tint, (void*)&tdata);
929 if (tssret != 0)
931 gnutls_assert();
932 Tspi_Context_FreeMemory(key_ctx, m.data);
933 return tss_err(tssret);
936 e.data = tdata;
937 e.size = tint;
939 ret = gnutls_pubkey_import_rsa_raw(pub, &m, &e);
941 Tspi_Context_FreeMemory(key_ctx, m.data);
942 Tspi_Context_FreeMemory(key_ctx, e.data);
944 if (ret < 0)
945 return gnutls_assert_val(ret);
947 if (psize)
948 *psize = e.size + m.size;
950 return 0;
955 static int
956 import_tpm_pubkey (gnutls_pubkey_t pkey,
957 const gnutls_datum_t * fdata,
958 gnutls_tpmkey_fmt_t format,
959 TSS_UUID *uuid,
960 TSS_FLAG storage,
961 const char *srk_password)
963 int err, ret;
964 struct tpm_ctx_st s;
966 ret = tpm_open_session(&s, srk_password);
967 if (ret < 0)
968 return gnutls_assert_val(ret);
970 if (fdata != NULL)
972 ret = load_key(s.tpm_ctx, s.srk, fdata, format, &s.tpm_key);
973 if (ret < 0)
975 gnutls_assert();
976 goto out_session;
979 else if (uuid)
981 err =
982 Tspi_Context_LoadKeyByUUID (s.tpm_ctx, storage,
983 *uuid, &s.tpm_key);
984 if (err)
986 gnutls_assert ();
987 ret = tss_err(err);
988 goto out_session;
991 else
993 gnutls_assert();
994 ret = GNUTLS_E_INVALID_REQUEST;
995 goto out_session;
998 ret = read_pubkey(pkey, s.tpm_key, NULL);
999 if (ret < 0)
1001 gnutls_assert();
1002 goto out_session;
1005 ret = 0;
1006 out_session:
1007 tpm_close_session(&s);
1008 return ret;
1011 static int
1012 import_tpm_pubkey_cb (gnutls_pubkey_t pkey,
1013 const gnutls_datum_t * fdata,
1014 gnutls_tpmkey_fmt_t format,
1015 TSS_UUID *uuid,
1016 TSS_FLAG storage,
1017 const char *srk_password)
1019 unsigned int attempts = 0;
1020 char pin1[GNUTLS_PKCS11_MAX_PIN_LEN];
1021 int ret;
1025 ret = import_tpm_pubkey(pkey, fdata, format, uuid, storage, srk_password);
1027 if (attempts > 3)
1028 break;
1030 if (ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR)
1032 ret = tpm_pin(&pkey->pin, &srk_uuid, storage, pin1, sizeof(pin1), attempts++);
1033 if (ret < 0)
1035 gnutls_assert();
1036 return GNUTLS_E_TPM_SRK_PASSWORD_ERROR;
1038 srk_password = pin1;
1041 while(ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR);
1043 if (ret < 0)
1044 gnutls_assert();
1045 return ret;
1050 * gnutls_pubkey_import_tpm_raw:
1051 * @pkey: The public key
1052 * @fdata: The TPM key to be imported
1053 * @format: The format of the private key
1054 * @srk_password: The password for the SRK key (optional)
1055 * @flags: One of the GNUTLS_PUBKEY_* flags
1057 * This function will import the public key from the provided TPM key
1058 * structure.
1060 * With respect to passwords the same as in
1061 * gnutls_pubkey_import_tpm_url() apply.
1063 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1064 * negative error value.
1066 * Since: 3.1.0
1069 gnutls_pubkey_import_tpm_raw (gnutls_pubkey_t pkey,
1070 const gnutls_datum_t * fdata,
1071 gnutls_tpmkey_fmt_t format,
1072 const char *srk_password,
1073 unsigned int flags)
1075 if (flags & GNUTLS_PUBKEY_DISABLE_CALLBACKS)
1076 return import_tpm_pubkey_cb(pkey, fdata, format, NULL, 0, srk_password);
1077 else
1078 return import_tpm_pubkey(pkey, fdata, format, NULL, 0, srk_password);
1082 * gnutls_pubkey_import_tpm_url:
1083 * @pkey: The public key
1084 * @url: The URL of the TPM key to be imported
1085 * @srk_password: The password for the SRK key (optional)
1086 * @flags: should be zero
1088 * This function will import the given private key to the abstract
1089 * #gnutls_privkey_t structure.
1091 * Note that unless %GNUTLS_PUBKEY_DISABLE_CALLBACKS
1092 * is specified, if incorrect (or NULL) passwords are given
1093 * the PKCS11 callback functions will be used to obtain the
1094 * correct passwords. Otherwise if the SRK password is wrong
1095 * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned.
1097 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1098 * negative error value.
1100 * Since: 3.1.0
1104 gnutls_pubkey_import_tpm_url (gnutls_pubkey_t pkey,
1105 const char* url,
1106 const char *srk_password,
1107 unsigned int flags)
1109 struct tpmkey_url_st durl;
1110 gnutls_datum_t fdata = { NULL, 0 };
1111 int ret;
1113 ret = decode_tpmkey_url(url, &durl);
1114 if (ret < 0)
1115 return gnutls_assert_val(ret);
1117 if (durl.filename)
1120 ret = gnutls_load_file(durl.filename, &fdata);
1121 if (ret < 0)
1123 gnutls_assert();
1124 goto cleanup;
1127 ret = gnutls_pubkey_import_tpm_raw (pkey, &fdata, GNUTLS_TPMKEY_FMT_CTK_PEM,
1128 srk_password, flags);
1129 if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1130 ret = gnutls_pubkey_import_tpm_raw (pkey, &fdata, GNUTLS_TPMKEY_FMT_DER,
1131 srk_password, flags);
1132 if (ret < 0)
1134 gnutls_assert();
1135 goto cleanup;
1138 else if (durl.uuid_set)
1140 if (flags & GNUTLS_PUBKEY_DISABLE_CALLBACKS)
1141 ret = import_tpm_pubkey (pkey, NULL, 0, &durl.uuid, durl.storage, srk_password);
1142 else
1143 ret = import_tpm_pubkey_cb (pkey, NULL, 0, &durl.uuid, durl.storage, srk_password);
1144 if (ret < 0)
1146 gnutls_assert();
1147 goto cleanup;
1151 ret = 0;
1152 cleanup:
1153 gnutls_free(fdata.data);
1154 clear_tpmkey_url(&durl);
1155 return ret;
1160 * gnutls_tpm_privkey_generate:
1161 * @pk: the public key algorithm
1162 * @bits: the security bits
1163 * @srk_password: a password to protect the exported key (optional)
1164 * @key_password: the password for the TPM (optional)
1165 * @format: the format of the private key
1166 * @pub_format: the format of the public key
1167 * @privkey: the generated key
1168 * @pubkey: the corresponding public key (may be null)
1169 * @flags: should be a list of GNUTLS_TPM_* flags
1171 * This function will generate a private key in the TPM
1172 * chip. The private key will be generated within the chip
1173 * and will be exported in a wrapped with TPM's master key
1174 * form. Furthermore the wrapped key can be protected with
1175 * the provided @password.
1177 * Note that bits in TPM is quantized value. If the input value
1178 * is not one of the allowed values, then it will be quantized to
1179 * one of 512, 1024, 2048, 4096, 8192 and 16384.
1181 * Allowed flags are:
1183 * %GNUTLS_TPM_KEY_SIGNING: Generate a signing key instead of a legacy,
1185 * %GNUTLS_TPM_REGISTER_KEY: Register the generate key in TPM. In that
1186 * case @privkey would contain a URL with the UUID.
1188 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1189 * negative error value.
1191 * Since: 3.1.0
1194 gnutls_tpm_privkey_generate (gnutls_pk_algorithm_t pk, unsigned int bits,
1195 const char* srk_password,
1196 const char* key_password,
1197 gnutls_tpmkey_fmt_t format,
1198 gnutls_x509_crt_fmt_t pub_format,
1199 gnutls_datum_t* privkey,
1200 gnutls_datum_t* pubkey,
1201 unsigned int flags)
1203 TSS_FLAG tpm_flags = TSS_KEY_VOLATILE;
1204 TSS_HKEY key_ctx;
1205 TSS_RESULT tssret;
1206 int ret;
1207 void* tdata;
1208 UINT32 tint;
1209 gnutls_datum_t tmpkey = {NULL, 0};
1210 TSS_HPOLICY key_policy;
1211 gnutls_pubkey_t pub;
1212 struct tpm_ctx_st s;
1213 TSS_FLAG storage_type;
1214 TSS_HTPM htpm;
1215 uint8_t buf[32];
1217 if (flags & GNUTLS_TPM_KEY_SIGNING)
1218 tpm_flags |= TSS_KEY_TYPE_SIGNING;
1219 else
1220 tpm_flags |= TSS_KEY_TYPE_LEGACY;
1222 if (flags & GNUTLS_TPM_KEY_USER)
1223 storage_type = TSS_PS_TYPE_USER;
1224 else
1225 storage_type = TSS_PS_TYPE_SYSTEM;
1227 if (bits <= 512)
1228 tpm_flags |= TSS_KEY_SIZE_512;
1229 else if (bits <= 1024)
1230 tpm_flags |= TSS_KEY_SIZE_1024;
1231 else if (bits <= 2048)
1232 tpm_flags |= TSS_KEY_SIZE_2048;
1233 else if (bits <= 4096)
1234 tpm_flags |= TSS_KEY_SIZE_4096;
1235 else if (bits <= 8192)
1236 tpm_flags |= TSS_KEY_SIZE_8192;
1237 else
1238 tpm_flags |= TSS_KEY_SIZE_16384;
1240 ret = tpm_open_session(&s, srk_password);
1241 if (ret < 0)
1242 return gnutls_assert_val(ret);
1244 /* put some randomness into TPM.
1245 * Let's not trust it completely.
1247 tssret = Tspi_Context_GetTpmObject(s.tpm_ctx, &htpm);
1248 if (tssret != 0)
1250 gnutls_assert();
1251 ret = tss_err(tssret);
1252 goto err_cc;
1256 ret = _gnutls_rnd(GNUTLS_RND_RANDOM, buf, sizeof(buf));
1257 if (ret < 0)
1259 gnutls_assert();
1260 goto err_cc;
1263 tssret = Tspi_TPM_StirRandom(htpm, sizeof(buf), buf);
1264 if (tssret)
1266 gnutls_assert();
1269 tssret = Tspi_Context_CreateObject(s.tpm_ctx, TSS_OBJECT_TYPE_RSAKEY, tpm_flags, &key_ctx);
1270 if (tssret != 0)
1272 gnutls_assert();
1273 ret = tss_err(tssret);
1274 goto err_cc;
1277 tssret = Tspi_SetAttribUint32(key_ctx, TSS_TSPATTRIB_KEY_INFO, TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
1278 TSS_SS_RSASSAPKCS1V15_DER);
1279 if (tssret != 0)
1281 gnutls_assert();
1282 ret = tss_err(tssret);
1283 goto err_sa;
1286 /* set the password of the actual key */
1287 if (key_password)
1289 tssret = Tspi_GetPolicyObject(key_ctx, TSS_POLICY_USAGE, &key_policy);
1290 if (tssret != 0)
1292 gnutls_assert();
1293 ret = tss_err(tssret);
1294 goto err_sa;
1297 tssret = myTspi_Policy_SetSecret(key_policy,
1298 SAFE_LEN(key_password), (void*)key_password);
1299 if (tssret != 0)
1301 gnutls_assert();
1302 ret = tss_err(tssret);
1303 goto err_sa;
1307 tssret = Tspi_Key_CreateKey(key_ctx, s.srk, 0);
1308 if (tssret != 0)
1310 gnutls_assert();
1311 ret = tss_err(tssret);
1312 goto err_sa;
1315 if (flags & GNUTLS_TPM_REGISTER_KEY)
1317 TSS_UUID key_uuid;
1319 ret = randomize_uuid(&key_uuid);
1320 if (ret < 0)
1322 gnutls_assert();
1323 goto err_sa;
1326 tssret = Tspi_Context_RegisterKey(s.tpm_ctx, key_ctx, storage_type,
1327 key_uuid, TSS_PS_TYPE_SYSTEM, srk_uuid);
1328 if (tssret != 0)
1330 gnutls_assert();
1331 ret = tss_err(tssret);
1332 goto err_sa;
1335 ret = encode_tpmkey_url((char**)&privkey->data, &key_uuid, storage_type);
1336 if (ret < 0)
1338 TSS_HKEY tkey;
1340 Tspi_Context_UnregisterKey(s.tpm_ctx, storage_type, key_uuid, &tkey);
1341 gnutls_assert();
1342 goto err_sa;
1344 privkey->size = strlen((char*)privkey->data);
1347 else /* get the key as blob */
1350 tssret = Tspi_GetAttribData(key_ctx, TSS_TSPATTRIB_KEY_BLOB,
1351 TSS_TSPATTRIB_KEYBLOB_BLOB, &tint, (void*)&tdata);
1352 if (tssret != 0)
1354 gnutls_assert();
1355 ret = tss_err(tssret);
1356 goto err_sa;
1360 if (format == GNUTLS_TPMKEY_FMT_CTK_PEM)
1362 ret = _gnutls_x509_encode_octet_string(tdata, tint, &tmpkey);
1363 if (ret < 0)
1365 gnutls_assert();
1366 goto cleanup;
1369 ret = _gnutls_fbase64_encode ("TSS KEY BLOB", tmpkey.data, tmpkey.size, privkey);
1370 if (ret < 0)
1372 gnutls_assert();
1373 goto cleanup;
1376 else
1378 UINT32 tint2;
1380 tmpkey.size = tint + 32; /* spec says no more than 20 */
1381 tmpkey.data = gnutls_malloc(tmpkey.size);
1382 if (tmpkey.data == NULL)
1384 gnutls_assert();
1385 ret = GNUTLS_E_MEMORY_ERROR;
1386 goto cleanup;
1389 tint2 = tmpkey.size;
1390 tssret = Tspi_EncodeDER_TssBlob(tint, tdata, TSS_BLOB_TYPE_PRIVATEKEY,
1391 &tint2, tmpkey.data);
1392 if (tssret != 0)
1394 gnutls_assert();
1395 ret = tss_err(tssret);
1396 goto cleanup;
1399 tmpkey.size = tint2;
1401 privkey->data = tmpkey.data;
1402 privkey->size = tmpkey.size;
1403 tmpkey.data = NULL;
1407 /* read the public key */
1408 if (pubkey != NULL)
1410 size_t psize;
1412 ret = gnutls_pubkey_init(&pub);
1413 if (ret < 0)
1415 gnutls_assert();
1416 goto privkey_cleanup;
1419 ret = read_pubkey(pub, key_ctx, &psize);
1420 if (ret < 0)
1422 gnutls_assert();
1423 goto privkey_cleanup;
1425 psize+=512;
1427 pubkey->data = gnutls_malloc(psize);
1428 if (pubkey->data == NULL)
1430 gnutls_assert();
1431 ret = GNUTLS_E_MEMORY_ERROR;
1432 goto pubkey_cleanup;
1435 ret = gnutls_pubkey_export(pub, pub_format, pubkey->data, &psize);
1436 if (ret < 0)
1438 gnutls_assert();
1439 goto pubkey_cleanup;
1441 pubkey->size = psize;
1443 gnutls_pubkey_deinit(pub);
1446 ret = 0;
1447 goto cleanup;
1449 pubkey_cleanup:
1450 gnutls_pubkey_deinit(pub);
1451 privkey_cleanup:
1452 gnutls_free(privkey->data);
1453 privkey->data = NULL;
1454 cleanup:
1455 gnutls_free(tmpkey.data);
1456 tmpkey.data = NULL;
1457 err_sa:
1458 Tspi_Context_CloseObject(s.tpm_ctx, key_ctx);
1459 err_cc:
1460 tpm_close_session(&s);
1461 return ret;
1466 * gnutls_tpm_key_list_deinit:
1467 * @list: a list of the keys
1469 * This function will deinitialize the list of stored keys in the TPM.
1471 * Since: 3.1.0
1473 void
1474 gnutls_tpm_key_list_deinit (gnutls_tpm_key_list_t list)
1476 if (list->tpm_ctx != 0) Tspi_Context_Close (list->tpm_ctx);
1477 gnutls_free(list);
1481 * gnutls_tpm_key_list_get_url:
1482 * @list: a list of the keys
1483 * @idx: The index of the key (starting from zero)
1484 * @url: The URL to be returned
1485 * @flags: should be zero
1487 * This function will return for each given index a URL of
1488 * the corresponding key.
1489 * If the provided index is out of bounds then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1490 * is returned.
1492 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1493 * negative error value.
1495 * Since: 3.1.0
1498 gnutls_tpm_key_list_get_url (gnutls_tpm_key_list_t list, unsigned int idx, char** url, unsigned int flags)
1500 if (idx >= list->size)
1501 return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1503 return encode_tpmkey_url(url, &list->ki[idx].keyUUID, list->ki[idx].persistentStorageType);
1507 * gnutls_tpm_get_registered:
1508 * @list: a list to store the keys
1510 * This function will get a list of stored keys in the TPM. The uuid
1511 * of those keys
1513 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1514 * negative error value.
1516 * Since: 3.1.0
1519 gnutls_tpm_get_registered (gnutls_tpm_key_list_t *list)
1521 TSS_RESULT tssret;
1522 int ret;
1524 *list = gnutls_calloc(1, sizeof(struct tpm_key_list_st));
1525 if (*list == NULL)
1526 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1528 tssret = Tspi_Context_Create (&(*list)->tpm_ctx);
1529 if (tssret)
1531 gnutls_assert ();
1532 ret = tss_err(tssret);
1533 goto cleanup;
1536 tssret = Tspi_Context_Connect ((*list)->tpm_ctx, NULL);
1537 if (tssret)
1539 gnutls_assert ();
1540 ret = tss_err(tssret);
1541 goto cleanup;
1544 tssret =
1545 Tspi_Context_GetRegisteredKeysByUUID2((*list)->tpm_ctx, TSS_PS_TYPE_SYSTEM,
1546 NULL, &(*list)->size, &(*list)->ki);
1547 if (tssret)
1549 gnutls_assert ();
1550 ret = tss_err(tssret);
1551 goto cleanup;
1553 return 0;
1555 cleanup:
1556 gnutls_tpm_key_list_deinit(*list);
1558 return ret;
1562 * gnutls_tpm_privkey_delete:
1563 * @url: the URL describing the key
1564 * @srk_password: a password for the SRK key
1566 * This function will unregister the private key from the TPM
1567 * chip.
1569 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1570 * negative error value.
1572 * Since: 3.1.0
1575 gnutls_tpm_privkey_delete (const char* url, const char* srk_password)
1577 struct tpm_ctx_st s;
1578 struct tpmkey_url_st durl;
1579 TSS_RESULT tssret;
1580 TSS_HKEY tkey;
1581 int ret;
1583 ret = decode_tpmkey_url(url, &durl);
1584 if (ret < 0)
1585 return gnutls_assert_val(ret);
1587 if (durl.uuid_set == 0)
1588 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1590 ret = tpm_open_session(&s, srk_password);
1591 if (ret < 0)
1592 return gnutls_assert_val(ret);
1594 tssret = Tspi_Context_UnregisterKey(s.tpm_ctx, durl.storage, durl.uuid, &tkey);
1595 if (tssret != 0)
1597 gnutls_assert();
1598 ret = tss_err(tssret);
1599 goto err_cc;
1602 ret = 0;
1603 err_cc:
1604 tpm_close_session(&s);
1605 return ret;