Line data Source code
1 : /*
2 : * OpenConnect (SSL + DTLS) VPN client
3 : *
4 : * Copyright © 2012 Free Software Foundation.
5 : * Copyright © 2008-2012 Intel Corporation.
6 : * Copyright © 2015-2016 Red Hat, Inc.
7 : *
8 : * Author: David Woodhouse <dwmw2@infradead.org>
9 : * Author: Nikos Mavrogiannopoulos
10 : *
11 : * GnuTLS is free software; you can redistribute it and/or
12 : * modify it under the terms of the GNU Lesser General Public License
13 : * as published by the Free Software Foundation; either version 2.1 of
14 : * the License, or (at your option) any later version.
15 : *
16 : * This library is distributed in the hope that it will be useful, but
17 : * WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 : * Lesser General Public License for more details.
20 : *
21 : * You should have received a copy of the GNU Lesser General Public License
22 : * along with this program. If not, see <https://www.gnu.org/licenses/>
23 : *
24 : */
25 :
26 : /*
27 : * TPM code based on client-tpm.c from
28 : * Carolin Latze <latze@angry-red-pla.net> and Tobias Soder
29 : */
30 :
31 : #include <config.h>
32 : #include <gnutls/gnutls.h>
33 : #include <gnutls/abstract.h>
34 : #include <gnutls/tpm.h>
35 : #include "gnutls_int.h"
36 :
37 : #ifdef HAVE_TROUSERS
38 :
39 : #include "errors.h"
40 : #include <pkcs11_int.h>
41 : #include <x509/common.h>
42 : #include <x509_b64.h>
43 : #include <random.h>
44 : #include <pin.h>
45 : #include <c-ctype.h>
46 :
47 : #include <dlfcn.h>
48 : #include <trousers/tss.h>
49 : #include <trousers/trousers.h>
50 :
51 : typedef char *(*Trspi_Error_Layer_func)(TSS_RESULT);
52 : typedef char *(*Trspi_Error_String_func)(TSS_RESULT);
53 : typedef TSS_RESULT (*Trspi_Error_Code_func)(TSS_RESULT);
54 :
55 : typedef TSS_RESULT (*Tspi_Context_CloseObject_func)(TSS_HCONTEXT, TSS_HOBJECT);
56 : typedef TSS_RESULT (*Tspi_Context_Close_func)(TSS_HCONTEXT);
57 : typedef TSS_RESULT (*Tspi_Context_CreateObject_func)(TSS_HCONTEXT, TSS_FLAG, TSS_FLAG, TSS_HOBJECT*);
58 : typedef TSS_RESULT (*Tspi_Context_FreeMemory_func)(TSS_HCONTEXT, BYTE*);
59 : typedef TSS_RESULT (*Tspi_Context_GetTpmObject_func)(TSS_HCONTEXT, TSS_HTPM*);
60 : typedef TSS_RESULT (*Tspi_Context_LoadKeyByUUID_func)(TSS_HCONTEXT, TSS_FLAG, TSS_UUID, TSS_HKEY*);
61 : typedef TSS_RESULT (*Tspi_Context_RegisterKey_func)(TSS_HCONTEXT, TSS_HKEY, TSS_FLAG, TSS_UUID, TSS_FLAG, TSS_UUID);
62 : typedef TSS_RESULT (*Tspi_Context_UnregisterKey_func)(TSS_HCONTEXT, TSS_FLAG, TSS_UUID, TSS_HKEY*);
63 : typedef TSS_RESULT (*Tspi_Key_CreateKey_func)(TSS_HKEY, TSS_HKEY, TSS_HPCRS);
64 : typedef TSS_RESULT (*Tspi_Hash_SetHashValue_func)(TSS_HHASH, UINT32, BYTE*);
65 : typedef TSS_RESULT (*Tspi_Hash_Sign_func)(TSS_HHASH, TSS_HKEY, UINT32*, BYTE**);
66 : typedef TSS_RESULT (*Tspi_Policy_SetSecret_func)(TSS_HPOLICY, TSS_FLAG, UINT32, BYTE*);
67 : typedef TSS_RESULT (*Tspi_Context_Create_func)(TSS_HCONTEXT*);
68 : typedef TSS_RESULT (*Tspi_Context_Connect_func)(TSS_HCONTEXT, TSS_UNICODE*);
69 : typedef TSS_RESULT (*Tspi_GetPolicyObject_func)(TSS_HOBJECT, TSS_FLAG, TSS_HPOLICY*);
70 : typedef TSS_RESULT (*Tspi_DecodeBER_TssBlob_func)(UINT32, BYTE*, UINT32*, UINT32*, BYTE*);
71 : typedef TSS_RESULT (*Tspi_Context_LoadKeyByBlob_func)(TSS_HCONTEXT, TSS_HKEY, UINT32, BYTE*, TSS_HKEY*);
72 : typedef TSS_RESULT (*Tspi_Policy_AssignToObject_func)(TSS_HPOLICY, TSS_HOBJECT);
73 : typedef TSS_RESULT (*Tspi_GetAttribData_func)(TSS_HOBJECT, TSS_FLAG, TSS_FLAG, UINT32*, BYTE**);
74 : typedef TSS_RESULT (*Tspi_GetAttribUint32_func)(TSS_HOBJECT, TSS_FLAG, TSS_FLAG, UINT32*);
75 : typedef TSS_RESULT (*Tspi_TPM_StirRandom_func)(TSS_HTPM, UINT32, BYTE*);
76 : typedef TSS_RESULT (*Tspi_SetAttribUint32_func)(TSS_HOBJECT, TSS_FLAG, TSS_FLAG, UINT32);
77 : typedef TSS_RESULT (*Tspi_EncodeDER_TssBlob_func)(UINT32, BYTE*, UINT32, UINT32*, BYTE*);
78 : typedef TSS_RESULT (*Tspi_Context_GetRegisteredKeysByUUID2_func)(TSS_HCONTEXT, TSS_FLAG, TSS_UUID*, UINT32*, TSS_KM_KEYINFO2**);
79 :
80 : static Tspi_Context_CloseObject_func pTspi_Context_CloseObject;
81 : static Tspi_Context_Close_func pTspi_Context_Close;
82 : static Tspi_Context_CreateObject_func pTspi_Context_CreateObject;
83 : static Tspi_Context_FreeMemory_func pTspi_Context_FreeMemory;
84 : static Tspi_Context_GetTpmObject_func pTspi_Context_GetTpmObject;
85 : static Tspi_Context_LoadKeyByUUID_func pTspi_Context_LoadKeyByUUID;
86 : static Tspi_Context_RegisterKey_func pTspi_Context_RegisterKey;
87 : static Tspi_Context_UnregisterKey_func pTspi_Context_UnregisterKey;
88 : static Tspi_Key_CreateKey_func pTspi_Key_CreateKey;
89 : static Tspi_Hash_SetHashValue_func pTspi_Hash_SetHashValue;
90 : static Tspi_Hash_Sign_func pTspi_Hash_Sign;
91 : static Tspi_Policy_SetSecret_func pTspi_Policy_SetSecret;
92 : static Tspi_Context_Create_func pTspi_Context_Create;
93 : static Tspi_Context_Connect_func pTspi_Context_Connect;
94 : static Tspi_GetPolicyObject_func pTspi_GetPolicyObject;
95 : static Tspi_DecodeBER_TssBlob_func pTspi_DecodeBER_TssBlob;
96 : static Tspi_Context_LoadKeyByBlob_func pTspi_Context_LoadKeyByBlob;
97 : static Tspi_Policy_AssignToObject_func pTspi_Policy_AssignToObject;
98 : static Tspi_GetAttribData_func pTspi_GetAttribData;
99 : static Tspi_GetAttribUint32_func pTspi_GetAttribUint32;
100 : static Tspi_Context_GetTpmObject_func pTspi_Context_GetTpmObject;
101 : static Tspi_TPM_StirRandom_func pTspi_TPM_StirRandom;
102 : static Tspi_SetAttribUint32_func pTspi_SetAttribUint32;
103 : static Tspi_EncodeDER_TssBlob_func pTspi_EncodeDER_TssBlob;
104 : static Tspi_Context_GetRegisteredKeysByUUID2_func pTspi_Context_GetRegisteredKeysByUUID2;
105 :
106 : static Trspi_Error_Layer_func pTrspi_Error_Layer;
107 : static Trspi_Error_String_func pTrspi_Error_String;
108 : static Trspi_Error_Code_func pTrspi_Error_Code;
109 :
110 : static void *tpm_dl = NULL;
111 :
112 : #define _DLSYM(dl, sym) \
113 : p##sym = dlsym(dl, #sym); \
114 : if (p##sym == NULL) { \
115 : dlclose(dl); \
116 : dl = NULL; \
117 : return -1; \
118 : }
119 :
120 35 : static int check_init(void)
121 : {
122 35 : if (tpm_dl == NULL) {
123 17 : tpm_dl = dlopen(TROUSERS_LIB, RTLD_LAZY);
124 17 : if (tpm_dl == NULL) {
125 0 : _gnutls_debug_log("couldn't open %s\n", TROUSERS_LIB);
126 0 : return -1;
127 : }
128 :
129 17 : _DLSYM(tpm_dl,Tspi_Context_CloseObject);
130 17 : _DLSYM(tpm_dl,Tspi_Context_Close);
131 17 : _DLSYM(tpm_dl,Tspi_Context_CreateObject);
132 17 : _DLSYM(tpm_dl,Tspi_Context_FreeMemory);
133 17 : _DLSYM(tpm_dl,Tspi_Context_GetTpmObject);
134 17 : _DLSYM(tpm_dl,Tspi_Context_LoadKeyByUUID);
135 17 : _DLSYM(tpm_dl,Tspi_Context_RegisterKey);
136 17 : _DLSYM(tpm_dl,Tspi_Context_UnregisterKey);
137 17 : _DLSYM(tpm_dl,Tspi_Key_CreateKey);
138 17 : _DLSYM(tpm_dl,Tspi_Hash_SetHashValue);
139 17 : _DLSYM(tpm_dl,Tspi_Hash_Sign);
140 17 : _DLSYM(tpm_dl,Tspi_Policy_SetSecret);
141 17 : _DLSYM(tpm_dl,Tspi_Context_Create);
142 17 : _DLSYM(tpm_dl,Tspi_Context_Connect);
143 17 : _DLSYM(tpm_dl,Tspi_GetPolicyObject);
144 17 : _DLSYM(tpm_dl,Tspi_DecodeBER_TssBlob);
145 17 : _DLSYM(tpm_dl,Tspi_Context_LoadKeyByBlob);
146 17 : _DLSYM(tpm_dl,Tspi_Policy_AssignToObject);
147 17 : _DLSYM(tpm_dl,Tspi_GetAttribData);
148 17 : _DLSYM(tpm_dl,Tspi_GetAttribUint32);
149 17 : _DLSYM(tpm_dl,Tspi_Context_GetTpmObject);
150 17 : _DLSYM(tpm_dl,Tspi_TPM_StirRandom);
151 17 : _DLSYM(tpm_dl,Tspi_SetAttribUint32);
152 17 : _DLSYM(tpm_dl,Tspi_EncodeDER_TssBlob);
153 17 : _DLSYM(tpm_dl,Tspi_Context_GetRegisteredKeysByUUID2);
154 :
155 17 : _DLSYM(tpm_dl,Trspi_Error_Layer);
156 17 : _DLSYM(tpm_dl,Trspi_Error_String);
157 17 : _DLSYM(tpm_dl,Trspi_Error_Code);
158 : }
159 :
160 : return 0;
161 : }
162 :
163 : #define CHECK_INIT \
164 : if (check_init() < 0) return gnutls_assert_val(GNUTLS_E_TPM_NO_LIB)
165 :
166 : #define CHECK_INIT_VOID \
167 : if (check_init() < 0) return
168 :
169 2196 : void _gnutls_tpm_global_deinit(void)
170 : {
171 2196 : if (tpm_dl) {
172 17 : dlclose(tpm_dl);
173 17 : tpm_dl = NULL;
174 : }
175 2196 : }
176 :
177 : struct tpm_ctx_st {
178 : TSS_HCONTEXT tpm_ctx;
179 : TSS_HKEY tpm_key;
180 : TSS_HPOLICY tpm_key_policy;
181 : TSS_HKEY srk;
182 : TSS_HPOLICY srk_policy;
183 : };
184 :
185 : struct tpm_key_list_st {
186 : UINT32 size;
187 : TSS_KM_KEYINFO2 *ki;
188 : TSS_HCONTEXT tpm_ctx;
189 : };
190 :
191 : static void tpm_close_session(struct tpm_ctx_st *s);
192 : static int import_tpm_key(gnutls_privkey_t pkey,
193 : const gnutls_datum_t * fdata,
194 : gnutls_tpmkey_fmt_t format,
195 : TSS_UUID * uuid,
196 : TSS_FLAG storage_type,
197 : const char *srk_password,
198 : const char *key_password);
199 : static int encode_tpmkey_url(char **url, const TSS_UUID * uuid,
200 : TSS_FLAG storage);
201 :
202 : /* TPM URL format: (draft-mavrogiannopoulos-tpmuri-01)
203 : *
204 : * tpmkey:file=/path/to/file
205 : * tpmkey:uuid=7f468c16-cb7f-11e1-824d-b3a4f4b20343;storage=user
206 : * tpmkey:uuid=7f468c16-cb7f-11e1-824d-b3a4f4b20343;storage=system
207 : *
208 : */
209 :
210 :
211 3 : static int tss_err_pwd(TSS_RESULT err, int pwd_error)
212 : {
213 3 : _gnutls_debug_log("TPM (%s) error: %s (%x)\n",
214 : pTrspi_Error_Layer(err), pTrspi_Error_String(err),
215 : (unsigned int) pTrspi_Error_Code(err));
216 :
217 3 : switch (ERROR_LAYER(err)) {
218 3 : case TSS_LAYER_TPM:
219 3 : switch (ERROR_CODE(err)) {
220 : case TPM_E_AUTHFAIL:
221 : return pwd_error;
222 0 : case TPM_E_NOSRK:
223 0 : return GNUTLS_E_TPM_UNINITIALIZED;
224 : default:
225 0 : return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
226 : }
227 0 : case TSS_LAYER_TCS:
228 : case TSS_LAYER_TSP:
229 0 : switch (ERROR_CODE(err)) {
230 : case TSS_E_COMM_FAILURE:
231 : case TSS_E_NO_CONNECTION:
232 : case TSS_E_CONNECTION_FAILED:
233 : case TSS_E_CONNECTION_BROKEN:
234 : return GNUTLS_E_TPM_SESSION_ERROR;
235 0 : case TSS_E_PS_KEY_NOTFOUND:
236 0 : return GNUTLS_E_TPM_KEY_NOT_FOUND;
237 : default:
238 0 : return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
239 : }
240 : default:
241 0 : return gnutls_assert_val(GNUTLS_E_TPM_ERROR);
242 : }
243 : }
244 :
245 : #define tss_err(x) tss_err_pwd(x, GNUTLS_E_TPM_SRK_PASSWORD_ERROR)
246 : #define tss_err_key(x) tss_err_pwd(x, GNUTLS_E_TPM_KEY_PASSWORD_ERROR)
247 :
248 5 : static void tpm_deinit_fn(gnutls_privkey_t key, void *_s)
249 : {
250 5 : struct tpm_ctx_st *s = _s;
251 :
252 5 : pTspi_Context_CloseObject(s->tpm_ctx, s->tpm_key_policy);
253 5 : pTspi_Context_CloseObject(s->tpm_ctx, s->tpm_key);
254 :
255 5 : tpm_close_session(s);
256 5 : gnutls_free(s);
257 5 : }
258 :
259 : static int
260 10 : tpm_sign_fn(gnutls_privkey_t key, void *_s,
261 : const gnutls_datum_t * data, gnutls_datum_t * sig)
262 : {
263 10 : struct tpm_ctx_st *s = _s;
264 10 : TSS_HHASH hash;
265 10 : int err;
266 :
267 10 : _gnutls_debug_log("TPM sign function called for %u bytes.\n",
268 : data->size);
269 :
270 20 : err =
271 10 : pTspi_Context_CreateObject(s->tpm_ctx,
272 : TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER,
273 : &hash);
274 10 : if (err) {
275 0 : gnutls_assert();
276 0 : _gnutls_debug_log("Failed to create TPM hash object: %s\n",
277 : pTrspi_Error_String(err));
278 0 : return GNUTLS_E_PK_SIGN_FAILED;
279 : }
280 10 : err = pTspi_Hash_SetHashValue(hash, data->size, data->data);
281 10 : if (err) {
282 0 : gnutls_assert();
283 0 : _gnutls_debug_log
284 : ("Failed to set value in TPM hash object: %s\n",
285 : pTrspi_Error_String(err));
286 0 : pTspi_Context_CloseObject(s->tpm_ctx, hash);
287 0 : return GNUTLS_E_PK_SIGN_FAILED;
288 : }
289 10 : err = pTspi_Hash_Sign(hash, s->tpm_key, &sig->size, &sig->data);
290 10 : pTspi_Context_CloseObject(s->tpm_ctx, hash);
291 10 : if (err) {
292 0 : if (s->tpm_key_policy || err != TPM_E_AUTHFAIL)
293 0 : _gnutls_debug_log
294 : ("TPM hash signature failed: %s\n",
295 : pTrspi_Error_String(err));
296 0 : if (err == TPM_E_AUTHFAIL)
297 : return GNUTLS_E_TPM_KEY_PASSWORD_ERROR;
298 : else
299 0 : return GNUTLS_E_PK_SIGN_FAILED;
300 : }
301 : return 0;
302 : }
303 :
304 : static const unsigned char nullpass[20];
305 : static const gnutls_datum_t nulldata = { (void *) nullpass, 20 };
306 :
307 : const TSS_UUID srk_uuid = TSS_UUID_SRK;
308 :
309 3 : static int tpm_pin(struct pin_info_st *pin_info, const TSS_UUID * uuid,
310 : TSS_FLAG storage, char *pin, unsigned int pin_size,
311 : unsigned int attempts)
312 : {
313 3 : unsigned int flags = 0;
314 3 : const char *label;
315 3 : char *url = NULL;
316 3 : int ret;
317 :
318 3 : if (attempts > 0)
319 0 : flags |= GNUTLS_PIN_WRONG;
320 :
321 3 : if (uuid) {
322 3 : if (memcmp(uuid, &srk_uuid, sizeof(TSS_UUID)) == 0) {
323 3 : label = "SRK";
324 :
325 3 : ret = encode_tpmkey_url(&url, uuid, storage);
326 3 : if (ret < 0)
327 0 : return gnutls_assert_val(ret);
328 : } else {
329 0 : label = "TPM";
330 :
331 0 : ret = encode_tpmkey_url(&url, uuid, storage);
332 0 : if (ret < 0)
333 0 : return gnutls_assert_val(ret);
334 : }
335 : } else
336 : label = "unknown";
337 :
338 3 : ret = _gnutls_retrieve_pin(pin_info, url, label, flags, pin, pin_size);
339 3 : if (ret < 0) {
340 0 : gnutls_assert();
341 0 : goto cleanup;
342 : }
343 :
344 : ret = 0;
345 3 : cleanup:
346 3 : gnutls_free(url);
347 3 : return ret;
348 : }
349 :
350 :
351 19 : static TSS_RESULT myTspi_Policy_SetSecret(TSS_HPOLICY hPolicy,
352 : UINT32 ulSecretLength,
353 : BYTE * rgbSecret)
354 : {
355 19 : if (rgbSecret == NULL) {
356 : /* Well known NULL key */
357 10 : return pTspi_Policy_SetSecret(hPolicy,
358 : TSS_SECRET_MODE_SHA1,
359 : sizeof(nullpass),
360 : (BYTE *) nullpass);
361 : } else { /* key is given */
362 :
363 9 : return pTspi_Policy_SetSecret(hPolicy,
364 : TSS_SECRET_MODE_PLAIN,
365 : ulSecretLength, rgbSecret);
366 : }
367 : }
368 :
369 : #define SAFE_LEN(x) (x==NULL?0:strlen(x))
370 :
371 18 : static int tpm_open_session(struct tpm_ctx_st *s, const char *_srk_password, unsigned allow_invalid_pass)
372 : {
373 18 : int err, ret;
374 18 : char *password = NULL;
375 :
376 18 : err = pTspi_Context_Create(&s->tpm_ctx);
377 18 : if (err) {
378 0 : gnutls_assert();
379 0 : return tss_err(err);
380 : }
381 :
382 18 : if (_srk_password != NULL) {
383 8 : gnutls_datum_t pout;
384 8 : ret = _gnutls_utf8_password_normalize(_srk_password, strlen(_srk_password), &pout, allow_invalid_pass);
385 8 : if (ret < 0) {
386 0 : gnutls_assert();
387 0 : goto out_tspi_ctx;
388 : }
389 8 : password = (char*)pout.data;
390 : }
391 :
392 18 : err = pTspi_Context_Connect(s->tpm_ctx, NULL);
393 18 : if (err) {
394 0 : gnutls_assert();
395 0 : ret = tss_err(err);
396 0 : goto out_tspi_ctx;
397 : }
398 :
399 36 : err =
400 18 : pTspi_Context_LoadKeyByUUID(s->tpm_ctx, TSS_PS_TYPE_SYSTEM,
401 : srk_uuid, &s->srk);
402 18 : if (err) {
403 0 : gnutls_assert();
404 0 : ret = tss_err(err);
405 0 : goto out_tspi_ctx;
406 : }
407 :
408 36 : err =
409 18 : pTspi_GetPolicyObject(s->srk, TSS_POLICY_USAGE, &s->srk_policy);
410 18 : if (err) {
411 0 : gnutls_assert();
412 0 : ret = tss_err(err);
413 0 : goto out_srk;
414 : }
415 :
416 26 : err = myTspi_Policy_SetSecret(s->srk_policy,
417 8 : SAFE_LEN(password),
418 : (BYTE *) password);
419 18 : if (err) {
420 0 : gnutls_assert();
421 0 : ret = tss_err(err);
422 0 : goto out_srkpol;
423 : }
424 18 : gnutls_free(password);
425 :
426 18 : return 0;
427 :
428 0 : out_srkpol:
429 0 : pTspi_Context_CloseObject(s->tpm_ctx, s->srk_policy);
430 0 : s->srk_policy = 0;
431 0 : out_srk:
432 0 : pTspi_Context_CloseObject(s->tpm_ctx, s->srk);
433 0 : s->srk = 0;
434 0 : out_tspi_ctx:
435 0 : pTspi_Context_Close(s->tpm_ctx);
436 0 : s->tpm_ctx = 0;
437 0 : gnutls_free(password);
438 0 : return ret;
439 :
440 : }
441 :
442 18 : static void tpm_close_session(struct tpm_ctx_st *s)
443 : {
444 18 : pTspi_Context_CloseObject(s->tpm_ctx, s->srk_policy);
445 18 : s->srk_policy = 0;
446 18 : pTspi_Context_CloseObject(s->tpm_ctx, s->srk);
447 18 : s->srk = 0;
448 18 : pTspi_Context_Close(s->tpm_ctx);
449 18 : s->tpm_ctx = 0;
450 18 : }
451 :
452 : static int
453 5 : import_tpm_key_cb(gnutls_privkey_t pkey, const gnutls_datum_t * fdata,
454 : gnutls_tpmkey_fmt_t format, TSS_UUID * uuid,
455 : TSS_FLAG storage, const char *srk_password,
456 : const char *key_password)
457 : {
458 5 : unsigned int attempts = 0;
459 8 : char pin1[GNUTLS_PKCS11_MAX_PIN_LEN];
460 8 : char pin2[GNUTLS_PKCS11_MAX_PIN_LEN];
461 8 : int ret, ret2;
462 :
463 8 : do {
464 8 : ret =
465 8 : import_tpm_key(pkey, fdata, format, uuid, storage,
466 : srk_password, key_password);
467 :
468 8 : if (attempts > 3)
469 : break;
470 :
471 8 : if (ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR) {
472 3 : ret2 =
473 3 : tpm_pin(&pkey->pin, &srk_uuid, storage, pin1,
474 : sizeof(pin1), attempts++);
475 3 : if (ret2 < 0) {
476 0 : gnutls_assert();
477 0 : return GNUTLS_E_TPM_SRK_PASSWORD_ERROR;
478 : }
479 : srk_password = pin1;
480 : }
481 :
482 8 : if (ret == GNUTLS_E_TPM_KEY_PASSWORD_ERROR) {
483 0 : ret2 =
484 0 : tpm_pin(&pkey->pin, uuid, storage, pin2,
485 : sizeof(pin2), attempts++);
486 0 : if (ret2 < 0) {
487 0 : gnutls_assert();
488 0 : return GNUTLS_E_TPM_KEY_PASSWORD_ERROR;
489 : }
490 : key_password = pin2;
491 : }
492 : }
493 8 : while (ret == GNUTLS_E_TPM_KEY_PASSWORD_ERROR
494 8 : || ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR);
495 :
496 5 : if (ret < 0)
497 0 : gnutls_assert();
498 : return ret;
499 : }
500 :
501 3 : static int load_key(TSS_HCONTEXT tpm_ctx, TSS_HKEY srk,
502 : const gnutls_datum_t * fdata,
503 : gnutls_tpmkey_fmt_t format, TSS_HKEY * tpm_key)
504 : {
505 3 : int ret, err;
506 3 : gnutls_datum_t asn1 = { NULL, 0 };
507 :
508 3 : if (format == GNUTLS_TPMKEY_FMT_CTK_PEM) {
509 3 : gnutls_datum_t td;
510 :
511 3 : ret =
512 3 : gnutls_pem_base64_decode2("TSS KEY BLOB", fdata,
513 : &asn1);
514 3 : if (ret) {
515 0 : gnutls_assert();
516 0 : _gnutls_debug_log
517 : ("Error decoding TSS key blob: %s\n",
518 : gnutls_strerror(ret));
519 0 : return ret;
520 : }
521 :
522 3 : ret =
523 6 : _gnutls_x509_decode_string(ASN1_ETYPE_OCTET_STRING,
524 3 : asn1.data, asn1.size, &td, 0);
525 3 : if (ret < 0) {
526 0 : gnutls_assert();
527 0 : goto cleanup;
528 : }
529 3 : gnutls_free(asn1.data);
530 3 : asn1.data = td.data;
531 3 : asn1.size = td.size;
532 : } else { /* DER */
533 :
534 0 : UINT32 tint2;
535 0 : UINT32 type;
536 :
537 0 : asn1.size = fdata->size;
538 0 : asn1.data = gnutls_malloc(asn1.size);
539 0 : if (asn1.data == NULL) {
540 0 : gnutls_assert();
541 0 : return GNUTLS_E_MEMORY_ERROR;
542 : }
543 :
544 0 : tint2 = asn1.size;
545 0 : err =
546 0 : pTspi_DecodeBER_TssBlob(fdata->size, fdata->data, &type,
547 : &tint2, asn1.data);
548 0 : if (err != 0) {
549 0 : gnutls_assert();
550 0 : ret = tss_err(err);
551 0 : goto cleanup;
552 : }
553 :
554 0 : asn1.size = tint2;
555 : }
556 :
557 : /* ... we get it here instead. */
558 6 : err = pTspi_Context_LoadKeyByBlob(tpm_ctx, srk,
559 3 : asn1.size, asn1.data, tpm_key);
560 3 : if (err != 0) {
561 1 : gnutls_assert();
562 1 : ret = tss_err(err);
563 1 : goto cleanup;
564 : }
565 :
566 : ret = 0;
567 :
568 3 : cleanup:
569 3 : gnutls_free(asn1.data);
570 :
571 3 : return ret;
572 : }
573 :
574 : static int
575 8 : import_tpm_key(gnutls_privkey_t pkey,
576 : const gnutls_datum_t * fdata,
577 : gnutls_tpmkey_fmt_t format,
578 : TSS_UUID * uuid,
579 : TSS_FLAG storage,
580 : const char *srk_password, const char *_key_password)
581 : {
582 8 : int err, ret;
583 8 : struct tpm_ctx_st *s;
584 8 : gnutls_datum_t tmp_sig;
585 8 : char *key_password = NULL;
586 8 : uint32_t authusage;
587 :
588 8 : s = gnutls_malloc(sizeof(*s));
589 8 : if (s == NULL) {
590 0 : gnutls_assert();
591 0 : return GNUTLS_E_MEMORY_ERROR;
592 : }
593 :
594 8 : if (_key_password != NULL) {
595 0 : gnutls_datum_t pout;
596 0 : ret = _gnutls_utf8_password_normalize(_key_password, strlen(_key_password), &pout, 1);
597 0 : if (ret < 0) {
598 0 : gnutls_assert();
599 0 : goto out_ctx;
600 : }
601 0 : key_password = (char*)pout.data;
602 : }
603 :
604 : /* normalization of srk_password happens in tpm_open_session() */
605 :
606 8 : ret = tpm_open_session(s, srk_password, 1);
607 8 : if (ret < 0) {
608 0 : gnutls_assert();
609 0 : goto out_ctx;
610 : }
611 :
612 8 : if (fdata != NULL) {
613 2 : ret =
614 2 : load_key(s->tpm_ctx, s->srk, fdata, format,
615 : &s->tpm_key);
616 2 : if (ret < 0) {
617 1 : gnutls_assert();
618 1 : goto out_session;
619 : }
620 6 : } else if (uuid) {
621 12 : err =
622 6 : pTspi_Context_LoadKeyByUUID(s->tpm_ctx, storage,
623 : *uuid, &s->tpm_key);
624 :
625 6 : if (err) {
626 2 : gnutls_assert();
627 2 : ret = tss_err(err);
628 2 : goto out_session;
629 : }
630 : } else {
631 0 : gnutls_assert();
632 0 : ret = GNUTLS_E_INVALID_REQUEST;
633 0 : goto out_session;
634 : }
635 :
636 5 : err = pTspi_GetAttribUint32(s->tpm_key, TSS_TSPATTRIB_KEY_INFO,
637 : TSS_TSPATTRIB_KEYINFO_AUTHUSAGE,
638 : &authusage);
639 5 : if (err) {
640 0 : gnutls_assert();
641 0 : ret = tss_err(err);
642 0 : goto out_session;
643 : }
644 :
645 5 : if (authusage) {
646 0 : if (!_key_password) {
647 0 : ret = GNUTLS_E_TPM_KEY_PASSWORD_ERROR;
648 0 : goto out_session;
649 : }
650 :
651 0 : err = pTspi_Context_CreateObject(s->tpm_ctx,
652 : TSS_OBJECT_TYPE_POLICY,
653 : TSS_POLICY_USAGE,
654 0 : &s->tpm_key_policy);
655 0 : if (err) {
656 0 : gnutls_assert();
657 0 : ret = tss_err(err);
658 0 : goto out_key;
659 : }
660 :
661 0 : err = pTspi_Policy_AssignToObject(s->tpm_key_policy,
662 : s->tpm_key);
663 0 : if (err) {
664 0 : gnutls_assert();
665 0 : ret = tss_err(err);
666 0 : goto out_key_policy;
667 : }
668 :
669 0 : err = myTspi_Policy_SetSecret(s->tpm_key_policy,
670 0 : SAFE_LEN(key_password),
671 : (void *) key_password);
672 :
673 0 : if (err) {
674 0 : gnutls_assert();
675 0 : ret = tss_err_key(err);
676 0 : goto out_key_policy;
677 : }
678 : }
679 :
680 5 : ret =
681 5 : gnutls_privkey_import_ext2(pkey, GNUTLS_PK_RSA, s,
682 : tpm_sign_fn, NULL, tpm_deinit_fn,
683 : 0);
684 5 : if (ret < 0) {
685 0 : gnutls_assert();
686 0 : goto out_session;
687 : }
688 :
689 5 : ret =
690 5 : gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA1, 0, &nulldata,
691 : &tmp_sig);
692 5 : if (ret < 0) {
693 0 : gnutls_assert();
694 0 : goto out_session;
695 : }
696 :
697 5 : gnutls_free(key_password);
698 :
699 5 : return 0;
700 0 : out_key_policy:
701 0 : pTspi_Context_CloseObject(s->tpm_ctx, s->tpm_key_policy);
702 0 : s->tpm_key_policy = 0;
703 0 : out_key:
704 0 : pTspi_Context_CloseObject(s->tpm_ctx, s->tpm_key);
705 0 : s->tpm_key = 0;
706 3 : out_session:
707 3 : _gnutls_privkey_cleanup(pkey);
708 3 : tpm_close_session(s);
709 3 : out_ctx:
710 3 : gnutls_free(s);
711 3 : gnutls_free(key_password);
712 3 : return ret;
713 : }
714 :
715 : /**
716 : * gnutls_privkey_import_tpm_raw:
717 : * @pkey: The private key
718 : * @fdata: The TPM key to be imported
719 : * @format: The format of the private key
720 : * @srk_password: The password for the SRK key (optional)
721 : * @key_password: A password for the key (optional)
722 : * @flags: should be zero
723 : *
724 : * This function will import the given private key to the abstract
725 : * #gnutls_privkey_t type.
726 : *
727 : * With respect to passwords the same as in gnutls_privkey_import_tpm_url() apply.
728 : *
729 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
730 : * negative error value.
731 : *
732 : * Since: 3.1.0
733 : *
734 : **/
735 : int
736 1 : gnutls_privkey_import_tpm_raw(gnutls_privkey_t pkey,
737 : const gnutls_datum_t * fdata,
738 : gnutls_tpmkey_fmt_t format,
739 : const char *srk_password,
740 : const char *key_password, unsigned int flags)
741 : {
742 1 : CHECK_INIT;
743 :
744 1 : if (flags & GNUTLS_PRIVKEY_DISABLE_CALLBACKS)
745 0 : return import_tpm_key(pkey, fdata, format, NULL, 0,
746 : srk_password, key_password);
747 : else
748 1 : return import_tpm_key_cb(pkey, fdata, format, NULL, 0,
749 : srk_password, key_password);
750 : }
751 :
752 : struct tpmkey_url_st {
753 : char *filename;
754 : TSS_UUID uuid;
755 : TSS_FLAG storage;
756 : unsigned int uuid_set;
757 : };
758 :
759 10 : static void clear_tpmkey_url(struct tpmkey_url_st *s)
760 : {
761 10 : gnutls_free(s->filename);
762 10 : memset(s, 0, sizeof(*s));
763 10 : }
764 :
765 : static int
766 2 : unescape_string(char *output, const char *input, size_t * size,
767 : char terminator)
768 : {
769 2 : gnutls_buffer_st str;
770 2 : int ret = 0;
771 2 : char *p;
772 2 : int len;
773 :
774 2 : _gnutls_buffer_init(&str);
775 :
776 : /* find terminator */
777 2 : p = strchr(input, terminator);
778 2 : if (p != NULL)
779 0 : len = p - input;
780 : else
781 2 : len = strlen(input);
782 :
783 2 : ret = _gnutls_buffer_append_data(&str, input, len);
784 2 : if (ret < 0) {
785 0 : gnutls_assert();
786 0 : return ret;
787 : }
788 :
789 2 : ret = _gnutls_buffer_unescape(&str);
790 2 : if (ret < 0) {
791 0 : gnutls_assert();
792 0 : return ret;
793 : }
794 :
795 2 : ret = _gnutls_buffer_append_data(&str, "", 1);
796 2 : if (ret < 0) {
797 0 : gnutls_assert();
798 0 : return ret;
799 : }
800 :
801 2 : ret = _gnutls_buffer_pop_data(&str, output, str.length);
802 2 : if (ret < 0) {
803 0 : gnutls_assert();
804 0 : return ret;
805 : }
806 :
807 2 : _gnutls_buffer_clear(&str);
808 :
809 2 : return ret;
810 : }
811 :
812 : #define UUID_SIZE 16
813 :
814 2 : static int randomize_uuid(TSS_UUID * uuid)
815 : {
816 2 : uint8_t raw_uuid[16];
817 2 : int ret;
818 :
819 2 : ret = gnutls_rnd(GNUTLS_RND_NONCE, raw_uuid, sizeof(raw_uuid));
820 2 : if (ret < 0)
821 0 : return gnutls_assert_val(ret);
822 :
823 : /* mark it as random uuid */
824 2 : raw_uuid[6] &= 0x0f;
825 2 : raw_uuid[6] |= 0x40;
826 2 : raw_uuid[8] &= 0x0f;
827 2 : raw_uuid[8] |= 0x80;
828 :
829 2 : memcpy(&uuid->ulTimeLow, raw_uuid, 4);
830 2 : memcpy(&uuid->usTimeMid, &raw_uuid[4], 2);
831 2 : memcpy(&uuid->usTimeHigh, &raw_uuid[6], 2);
832 2 : uuid->bClockSeqHigh = raw_uuid[8];
833 2 : uuid->bClockSeqLow = raw_uuid[9];
834 2 : memcpy(&uuid->rgbNode, &raw_uuid[10], 6);
835 :
836 2 : return 0;
837 : }
838 :
839 11 : static int encode_tpmkey_url(char **url, const TSS_UUID * uuid,
840 : TSS_FLAG storage)
841 : {
842 11 : uint8_t u1[UUID_SIZE];
843 11 : gnutls_buffer_st buf;
844 11 : gnutls_datum_t dret;
845 11 : int ret;
846 :
847 11 : _gnutls_buffer_init(&buf);
848 :
849 11 : memcpy(u1, &uuid->ulTimeLow, 4);
850 11 : memcpy(&u1[4], &uuid->usTimeMid, 2);
851 11 : memcpy(&u1[6], &uuid->usTimeHigh, 2);
852 11 : u1[8] = uuid->bClockSeqHigh;
853 11 : u1[9] = uuid->bClockSeqLow;
854 11 : memcpy(&u1[10], uuid->rgbNode, 6);
855 :
856 11 : ret = _gnutls_buffer_append_str(&buf, "tpmkey:uuid=");
857 11 : if (ret < 0) {
858 0 : gnutls_assert();
859 0 : goto cleanup;
860 : }
861 :
862 11 : ret =
863 22 : _gnutls_buffer_append_printf(&buf,
864 : "%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x",
865 11 : (unsigned int) u1[0],
866 11 : (unsigned int) u1[1],
867 11 : (unsigned int) u1[2],
868 11 : (unsigned int) u1[3],
869 11 : (unsigned int) u1[4],
870 11 : (unsigned int) u1[5],
871 11 : (unsigned int) u1[6],
872 11 : (unsigned int) u1[7],
873 11 : (unsigned int) u1[8],
874 11 : (unsigned int) u1[9],
875 11 : (unsigned int) u1[10],
876 11 : (unsigned int) u1[11],
877 11 : (unsigned int) u1[12],
878 11 : (unsigned int) u1[13],
879 11 : (unsigned int) u1[14],
880 11 : (unsigned int) u1[15]);
881 11 : if (ret < 0) {
882 0 : gnutls_assert();
883 0 : goto cleanup;
884 : }
885 :
886 11 : ret =
887 22 : _gnutls_buffer_append_printf(&buf, ";storage=%s",
888 : (storage ==
889 : TSS_PS_TYPE_USER) ? "user" :
890 : "system");
891 11 : if (ret < 0) {
892 0 : gnutls_assert();
893 0 : goto cleanup;
894 : }
895 :
896 11 : ret = _gnutls_buffer_to_datum(&buf, &dret, 1);
897 11 : if (ret < 0) {
898 0 : gnutls_assert();
899 0 : goto cleanup;
900 : }
901 :
902 11 : *url = (char *) dret.data;
903 :
904 11 : return 0;
905 0 : cleanup:
906 0 : _gnutls_buffer_clear(&buf);
907 0 : return ret;
908 : }
909 :
910 12 : static int decode_tpmkey_url(const char *url, struct tpmkey_url_st *s)
911 : {
912 12 : char *p;
913 12 : size_t size;
914 12 : int ret;
915 12 : unsigned int i, j;
916 :
917 12 : if (strstr(url, "tpmkey:") == NULL)
918 0 : return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
919 :
920 12 : memset(s, 0, sizeof(*s));
921 :
922 12 : p = strstr(url, "file=");
923 12 : if (p != NULL) {
924 2 : p += sizeof("file=") - 1;
925 2 : size = strlen(p);
926 2 : s->filename = gnutls_malloc(size + 1);
927 2 : if (s->filename == NULL)
928 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
929 :
930 2 : ret = unescape_string(s->filename, p, &size, ';');
931 2 : if (ret < 0) {
932 0 : gnutls_assert();
933 0 : goto cleanup;
934 : }
935 2 : s->filename[size] = 0;
936 10 : } else if ((p = strstr(url, "uuid=")) != NULL) {
937 10 : char tmp_uuid[33];
938 10 : uint8_t raw_uuid[16];
939 10 : gnutls_datum_t tmp;
940 :
941 10 : p += sizeof("uuid=") - 1;
942 10 : size = strlen(p);
943 :
944 370 : for (j = i = 0; i < size; i++) {
945 360 : if (j == sizeof(tmp_uuid) - 1) {
946 : break;
947 : }
948 680 : if (c_isalnum(p[i]))
949 320 : tmp_uuid[j++] = p[i];
950 : }
951 10 : tmp_uuid[j] = 0;
952 :
953 10 : tmp.data = (void*)tmp_uuid;
954 10 : tmp.size = strlen(tmp_uuid);
955 10 : size = sizeof(raw_uuid);
956 10 : ret =
957 10 : gnutls_hex_decode(&tmp, raw_uuid,
958 : &size);
959 10 : if (ret < 0) {
960 0 : gnutls_assert();
961 0 : goto cleanup;
962 : }
963 :
964 10 : memcpy(&s->uuid.ulTimeLow, raw_uuid, 4);
965 10 : memcpy(&s->uuid.usTimeMid, &raw_uuid[4], 2);
966 10 : memcpy(&s->uuid.usTimeHigh, &raw_uuid[6], 2);
967 10 : s->uuid.bClockSeqHigh = raw_uuid[8];
968 10 : s->uuid.bClockSeqLow = raw_uuid[9];
969 10 : memcpy(&s->uuid.rgbNode, &raw_uuid[10], 6);
970 10 : s->uuid_set = 1;
971 : } else {
972 0 : return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
973 : }
974 :
975 12 : if (strstr(url, "storage=user") != NULL)
976 0 : s->storage = TSS_PS_TYPE_USER;
977 : else
978 12 : s->storage = TSS_PS_TYPE_SYSTEM;
979 :
980 : return 0;
981 :
982 0 : cleanup:
983 0 : clear_tpmkey_url(s);
984 0 : return ret;
985 : }
986 :
987 : /**
988 : * gnutls_privkey_import_tpm_url:
989 : * @pkey: The private key
990 : * @url: The URL of the TPM key to be imported
991 : * @srk_password: The password for the SRK key (optional)
992 : * @key_password: A password for the key (optional)
993 : * @flags: One of the GNUTLS_PRIVKEY_* flags
994 : *
995 : * This function will import the given private key to the abstract
996 : * #gnutls_privkey_t type.
997 : *
998 : * Note that unless %GNUTLS_PRIVKEY_DISABLE_CALLBACKS
999 : * is specified, if incorrect (or NULL) passwords are given
1000 : * the PKCS11 callback functions will be used to obtain the
1001 : * correct passwords. Otherwise if the SRK password is wrong
1002 : * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned and if the key password
1003 : * is wrong or not provided then %GNUTLS_E_TPM_KEY_PASSWORD_ERROR
1004 : * is returned.
1005 : *
1006 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1007 : * negative error value.
1008 : *
1009 : * Since: 3.1.0
1010 : *
1011 : **/
1012 : int
1013 5 : gnutls_privkey_import_tpm_url(gnutls_privkey_t pkey,
1014 : const char *url,
1015 : const char *srk_password,
1016 : const char *key_password, unsigned int flags)
1017 : {
1018 5 : struct tpmkey_url_st durl;
1019 5 : gnutls_datum_t fdata = { NULL, 0 };
1020 5 : int ret;
1021 :
1022 5 : CHECK_INIT;
1023 :
1024 5 : ret = decode_tpmkey_url(url, &durl);
1025 5 : if (ret < 0)
1026 0 : return gnutls_assert_val(ret);
1027 :
1028 5 : if (durl.filename) {
1029 1 : ret = gnutls_load_file(durl.filename, &fdata);
1030 1 : if (ret < 0) {
1031 0 : gnutls_assert();
1032 0 : _gnutls_debug_log("Error loading %s\n",
1033 : durl.filename);
1034 0 : goto cleanup;
1035 : }
1036 :
1037 1 : ret =
1038 1 : gnutls_privkey_import_tpm_raw(pkey, &fdata,
1039 : GNUTLS_TPMKEY_FMT_CTK_PEM,
1040 : srk_password,
1041 : key_password, flags);
1042 1 : if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1043 0 : ret =
1044 0 : gnutls_privkey_import_tpm_raw(pkey, &fdata,
1045 : GNUTLS_TPMKEY_FMT_RAW,
1046 : srk_password,
1047 : key_password,
1048 : flags);
1049 :
1050 1 : if (ret < 0) {
1051 0 : gnutls_assert();
1052 0 : goto cleanup;
1053 : }
1054 4 : } else if (durl.uuid_set) {
1055 4 : if (flags & GNUTLS_PRIVKEY_DISABLE_CALLBACKS)
1056 0 : ret =
1057 0 : import_tpm_key(pkey, NULL, 0, &durl.uuid,
1058 : durl.storage, srk_password,
1059 : key_password);
1060 : else
1061 4 : ret =
1062 4 : import_tpm_key_cb(pkey, NULL, 0, &durl.uuid,
1063 : durl.storage, srk_password,
1064 : key_password);
1065 4 : if (ret < 0) {
1066 0 : gnutls_assert();
1067 0 : goto cleanup;
1068 : }
1069 : }
1070 :
1071 : ret = 0;
1072 5 : cleanup:
1073 5 : gnutls_free(fdata.data);
1074 5 : clear_tpmkey_url(&durl);
1075 5 : return ret;
1076 : }
1077 :
1078 :
1079 : /* reads the RSA public key from the given TSS key.
1080 : * If psize is non-null it contains the total size of the parameters
1081 : * in bytes */
1082 8 : static int read_pubkey(gnutls_pubkey_t pub, TSS_HKEY key_ctx,
1083 : size_t * psize)
1084 : {
1085 8 : void *tdata;
1086 8 : UINT32 tint;
1087 8 : TSS_RESULT tssret;
1088 8 : gnutls_datum_t m, e;
1089 8 : int ret;
1090 :
1091 : /* read the public key */
1092 :
1093 8 : tssret = pTspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
1094 : TSS_TSPATTRIB_KEYINFO_RSA_MODULUS,
1095 : &tint, (void *) &tdata);
1096 8 : if (tssret != 0) {
1097 0 : gnutls_assert();
1098 0 : return tss_err(tssret);
1099 : }
1100 :
1101 8 : m.data = tdata;
1102 8 : m.size = tint;
1103 :
1104 8 : tssret = pTspi_GetAttribData(key_ctx, TSS_TSPATTRIB_RSAKEY_INFO,
1105 : TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT,
1106 : &tint, (void *) &tdata);
1107 8 : if (tssret != 0) {
1108 0 : gnutls_assert();
1109 0 : pTspi_Context_FreeMemory(key_ctx, m.data);
1110 0 : return tss_err(tssret);
1111 : }
1112 :
1113 8 : e.data = tdata;
1114 8 : e.size = tint;
1115 :
1116 8 : ret = gnutls_pubkey_import_rsa_raw(pub, &m, &e);
1117 :
1118 8 : pTspi_Context_FreeMemory(key_ctx, m.data);
1119 8 : pTspi_Context_FreeMemory(key_ctx, e.data);
1120 :
1121 8 : if (ret < 0)
1122 0 : return gnutls_assert_val(ret);
1123 :
1124 8 : if (psize)
1125 3 : *psize = e.size + m.size;
1126 :
1127 : return 0;
1128 : }
1129 :
1130 :
1131 :
1132 : static int
1133 5 : import_tpm_pubkey(gnutls_pubkey_t pkey,
1134 : const gnutls_datum_t * fdata,
1135 : gnutls_tpmkey_fmt_t format,
1136 : TSS_UUID * uuid,
1137 : TSS_FLAG storage, const char *srk_password)
1138 : {
1139 5 : int err, ret;
1140 5 : struct tpm_ctx_st s;
1141 :
1142 5 : ret = tpm_open_session(&s, srk_password, 1);
1143 5 : if (ret < 0)
1144 0 : return gnutls_assert_val(ret);
1145 :
1146 5 : if (fdata != NULL) {
1147 1 : ret =
1148 1 : load_key(s.tpm_ctx, s.srk, fdata, format, &s.tpm_key);
1149 1 : if (ret < 0) {
1150 0 : gnutls_assert();
1151 0 : goto out_session;
1152 : }
1153 4 : } else if (uuid) {
1154 8 : err =
1155 4 : pTspi_Context_LoadKeyByUUID(s.tpm_ctx, storage,
1156 : *uuid, &s.tpm_key);
1157 4 : if (err) {
1158 0 : gnutls_assert();
1159 0 : ret = tss_err(err);
1160 0 : goto out_session;
1161 : }
1162 : } else {
1163 0 : gnutls_assert();
1164 0 : ret = GNUTLS_E_INVALID_REQUEST;
1165 0 : goto out_session;
1166 : }
1167 :
1168 5 : ret = read_pubkey(pkey, s.tpm_key, NULL);
1169 5 : if (ret < 0) {
1170 0 : gnutls_assert();
1171 0 : goto out_session;
1172 : }
1173 :
1174 : ret = 0;
1175 5 : out_session:
1176 5 : tpm_close_session(&s);
1177 5 : return ret;
1178 : }
1179 :
1180 : static int
1181 4 : import_tpm_pubkey_cb(gnutls_pubkey_t pkey,
1182 : const gnutls_datum_t * fdata,
1183 : gnutls_tpmkey_fmt_t format,
1184 : TSS_UUID * uuid,
1185 : TSS_FLAG storage, const char *srk_password)
1186 : {
1187 4 : unsigned int attempts = 0;
1188 4 : char pin1[GNUTLS_PKCS11_MAX_PIN_LEN];
1189 4 : int ret, sret;
1190 :
1191 4 : do {
1192 4 : ret =
1193 4 : import_tpm_pubkey(pkey, fdata, format, uuid, storage,
1194 : srk_password);
1195 :
1196 4 : if (attempts > 3)
1197 : break;
1198 :
1199 4 : if (ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR) {
1200 0 : sret =
1201 0 : tpm_pin(&pkey->pin, &srk_uuid, storage, pin1,
1202 : sizeof(pin1), attempts++);
1203 0 : if (sret < 0) {
1204 0 : gnutls_assert();
1205 0 : return GNUTLS_E_TPM_SRK_PASSWORD_ERROR;
1206 : }
1207 : srk_password = pin1;
1208 : }
1209 : }
1210 4 : while (ret == GNUTLS_E_TPM_SRK_PASSWORD_ERROR);
1211 :
1212 4 : if (ret < 0)
1213 0 : gnutls_assert();
1214 : return ret;
1215 : }
1216 :
1217 :
1218 : /**
1219 : * gnutls_pubkey_import_tpm_raw:
1220 : * @pkey: The public key
1221 : * @fdata: The TPM key to be imported
1222 : * @format: The format of the private key
1223 : * @srk_password: The password for the SRK key (optional)
1224 : * @flags: One of the GNUTLS_PUBKEY_* flags
1225 : *
1226 : * This function will import the public key from the provided TPM key
1227 : * structure.
1228 : *
1229 : * With respect to passwords the same as in
1230 : * gnutls_pubkey_import_tpm_url() apply.
1231 : *
1232 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1233 : * negative error value.
1234 : *
1235 : * Since: 3.1.0
1236 : **/
1237 : int
1238 1 : gnutls_pubkey_import_tpm_raw(gnutls_pubkey_t pkey,
1239 : const gnutls_datum_t * fdata,
1240 : gnutls_tpmkey_fmt_t format,
1241 : const char *srk_password, unsigned int flags)
1242 : {
1243 1 : CHECK_INIT;
1244 :
1245 1 : if (flags & GNUTLS_PUBKEY_DISABLE_CALLBACKS)
1246 0 : return import_tpm_pubkey_cb(pkey, fdata, format, NULL, 0,
1247 : srk_password);
1248 : else
1249 1 : return import_tpm_pubkey(pkey, fdata, format, NULL, 0,
1250 : srk_password);
1251 : }
1252 :
1253 : /**
1254 : * gnutls_pubkey_import_tpm_url:
1255 : * @pkey: The public key
1256 : * @url: The URL of the TPM key to be imported
1257 : * @srk_password: The password for the SRK key (optional)
1258 : * @flags: should be zero
1259 : *
1260 : * This function will import the given private key to the abstract
1261 : * #gnutls_privkey_t type.
1262 : *
1263 : * Note that unless %GNUTLS_PUBKEY_DISABLE_CALLBACKS
1264 : * is specified, if incorrect (or NULL) passwords are given
1265 : * the PKCS11 callback functions will be used to obtain the
1266 : * correct passwords. Otherwise if the SRK password is wrong
1267 : * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned.
1268 : *
1269 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1270 : * negative error value.
1271 : *
1272 : * Since: 3.1.0
1273 : *
1274 : **/
1275 : int
1276 5 : gnutls_pubkey_import_tpm_url(gnutls_pubkey_t pkey,
1277 : const char *url,
1278 : const char *srk_password, unsigned int flags)
1279 : {
1280 5 : struct tpmkey_url_st durl;
1281 5 : gnutls_datum_t fdata = { NULL, 0 };
1282 5 : int ret;
1283 :
1284 5 : CHECK_INIT;
1285 :
1286 5 : ret = decode_tpmkey_url(url, &durl);
1287 5 : if (ret < 0)
1288 0 : return gnutls_assert_val(ret);
1289 :
1290 5 : if (durl.filename) {
1291 :
1292 1 : ret = gnutls_load_file(durl.filename, &fdata);
1293 1 : if (ret < 0) {
1294 0 : gnutls_assert();
1295 0 : goto cleanup;
1296 : }
1297 :
1298 1 : ret =
1299 1 : gnutls_pubkey_import_tpm_raw(pkey, &fdata,
1300 : GNUTLS_TPMKEY_FMT_CTK_PEM,
1301 : srk_password, flags);
1302 1 : if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
1303 0 : ret =
1304 0 : gnutls_pubkey_import_tpm_raw(pkey, &fdata,
1305 : GNUTLS_TPMKEY_FMT_RAW,
1306 : srk_password,
1307 : flags);
1308 1 : if (ret < 0) {
1309 0 : gnutls_assert();
1310 0 : goto cleanup;
1311 : }
1312 4 : } else if (durl.uuid_set) {
1313 4 : if (flags & GNUTLS_PUBKEY_DISABLE_CALLBACKS)
1314 0 : ret =
1315 0 : import_tpm_pubkey(pkey, NULL, 0, &durl.uuid,
1316 : durl.storage, srk_password);
1317 : else
1318 4 : ret =
1319 4 : import_tpm_pubkey_cb(pkey, NULL, 0, &durl.uuid,
1320 : durl.storage,
1321 : srk_password);
1322 4 : if (ret < 0) {
1323 0 : gnutls_assert();
1324 0 : goto cleanup;
1325 : }
1326 : }
1327 :
1328 : ret = 0;
1329 5 : cleanup:
1330 5 : gnutls_free(fdata.data);
1331 5 : clear_tpmkey_url(&durl);
1332 5 : return ret;
1333 : }
1334 :
1335 :
1336 : /**
1337 : * gnutls_tpm_privkey_generate:
1338 : * @pk: the public key algorithm
1339 : * @bits: the security bits
1340 : * @srk_password: a password to protect the exported key (optional)
1341 : * @key_password: the password for the TPM (optional)
1342 : * @format: the format of the private key
1343 : * @pub_format: the format of the public key
1344 : * @privkey: the generated key
1345 : * @pubkey: the corresponding public key (may be null)
1346 : * @flags: should be a list of GNUTLS_TPM_* flags
1347 : *
1348 : * This function will generate a private key in the TPM
1349 : * chip. The private key will be generated within the chip
1350 : * and will be exported in a wrapped with TPM's master key
1351 : * form. Furthermore the wrapped key can be protected with
1352 : * the provided @password.
1353 : *
1354 : * Note that bits in TPM is quantized value. If the input value
1355 : * is not one of the allowed values, then it will be quantized to
1356 : * one of 512, 1024, 2048, 4096, 8192 and 16384.
1357 : *
1358 : * Allowed flags are:
1359 : *
1360 : * %GNUTLS_TPM_KEY_SIGNING: Generate a signing key instead of a legacy,
1361 : *
1362 : * %GNUTLS_TPM_REGISTER_KEY: Register the generate key in TPM. In that
1363 : * case @privkey would contain a URL with the UUID.
1364 : *
1365 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1366 : * negative error value.
1367 : *
1368 : * Since: 3.1.0
1369 : **/
1370 : int
1371 3 : gnutls_tpm_privkey_generate(gnutls_pk_algorithm_t pk, unsigned int bits,
1372 : const char *srk_password,
1373 : const char *key_password,
1374 : gnutls_tpmkey_fmt_t format,
1375 : gnutls_x509_crt_fmt_t pub_format,
1376 : gnutls_datum_t * privkey,
1377 : gnutls_datum_t * pubkey, unsigned int flags)
1378 : {
1379 3 : TSS_FLAG tpm_flags = TSS_KEY_VOLATILE;
1380 3 : TSS_HKEY key_ctx;
1381 3 : TSS_RESULT tssret;
1382 3 : int ret;
1383 3 : void *tdata;
1384 3 : UINT32 tint;
1385 3 : gnutls_datum_t tmpkey = { NULL, 0 };
1386 3 : TSS_HPOLICY key_policy;
1387 3 : gnutls_pubkey_t pub;
1388 3 : struct tpm_ctx_st s;
1389 3 : TSS_FLAG storage_type;
1390 3 : TSS_HTPM htpm;
1391 3 : uint8_t buf[32];
1392 :
1393 3 : CHECK_INIT;
1394 :
1395 3 : privkey->data = NULL;
1396 3 : if (pubkey != NULL)
1397 3 : pubkey->data = NULL;
1398 :
1399 3 : if (flags & GNUTLS_TPM_KEY_SIGNING)
1400 : tpm_flags |= TSS_KEY_TYPE_SIGNING;
1401 : else
1402 0 : tpm_flags |= TSS_KEY_TYPE_LEGACY;
1403 :
1404 3 : if (flags & GNUTLS_TPM_KEY_USER)
1405 : storage_type = TSS_PS_TYPE_USER;
1406 : else
1407 3 : storage_type = TSS_PS_TYPE_SYSTEM;
1408 :
1409 3 : if (bits <= 512)
1410 0 : tpm_flags |= TSS_KEY_SIZE_512;
1411 3 : else if (bits <= 1024)
1412 0 : tpm_flags |= TSS_KEY_SIZE_1024;
1413 3 : else if (bits <= 2048)
1414 3 : tpm_flags |= TSS_KEY_SIZE_2048;
1415 0 : else if (bits <= 4096)
1416 0 : tpm_flags |= TSS_KEY_SIZE_4096;
1417 0 : else if (bits <= 8192)
1418 0 : tpm_flags |= TSS_KEY_SIZE_8192;
1419 : else
1420 0 : tpm_flags |= TSS_KEY_SIZE_16384;
1421 :
1422 3 : ret = tpm_open_session(&s, srk_password, 0);
1423 3 : if (ret < 0)
1424 0 : return gnutls_assert_val(ret);
1425 :
1426 : /* put some randomness into TPM.
1427 : * Let's not trust it completely.
1428 : */
1429 3 : tssret = pTspi_Context_GetTpmObject(s.tpm_ctx, &htpm);
1430 3 : if (tssret != 0) {
1431 0 : gnutls_assert();
1432 0 : ret = tss_err(tssret);
1433 0 : goto err_cc;
1434 : }
1435 :
1436 :
1437 3 : ret = gnutls_rnd(GNUTLS_RND_RANDOM, buf, sizeof(buf));
1438 3 : if (ret < 0) {
1439 0 : gnutls_assert();
1440 0 : goto err_cc;
1441 : }
1442 :
1443 3 : tssret = pTspi_TPM_StirRandom(htpm, sizeof(buf), buf);
1444 3 : if (tssret) {
1445 0 : gnutls_assert();
1446 : }
1447 :
1448 3 : tssret =
1449 3 : pTspi_Context_CreateObject(s.tpm_ctx, TSS_OBJECT_TYPE_RSAKEY,
1450 : tpm_flags, &key_ctx);
1451 3 : if (tssret != 0) {
1452 0 : gnutls_assert();
1453 0 : ret = tss_err(tssret);
1454 0 : goto err_cc;
1455 : }
1456 :
1457 3 : tssret =
1458 3 : pTspi_SetAttribUint32(key_ctx, TSS_TSPATTRIB_KEY_INFO,
1459 : TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
1460 : TSS_SS_RSASSAPKCS1V15_DER);
1461 3 : if (tssret != 0) {
1462 0 : gnutls_assert();
1463 0 : ret = tss_err(tssret);
1464 0 : goto err_sa;
1465 : }
1466 :
1467 : /* set the password of the actual key */
1468 3 : if (key_password) {
1469 1 : gnutls_datum_t pout;
1470 1 : char *password = NULL;
1471 :
1472 1 : tssret =
1473 1 : pTspi_GetPolicyObject(key_ctx, TSS_POLICY_USAGE,
1474 : &key_policy);
1475 1 : if (tssret != 0) {
1476 0 : gnutls_assert();
1477 0 : ret = tss_err(tssret);
1478 0 : goto err_sa;
1479 : }
1480 :
1481 1 : ret = _gnutls_utf8_password_normalize(key_password, strlen(key_password), &pout, 0);
1482 1 : if (ret < 0) {
1483 0 : gnutls_assert();
1484 0 : goto err_sa;
1485 : }
1486 1 : password = (char*)pout.data;
1487 :
1488 2 : tssret = myTspi_Policy_SetSecret(key_policy,
1489 1 : SAFE_LEN(password),
1490 : (void *)password);
1491 1 : gnutls_free(password);
1492 1 : if (tssret != 0) {
1493 0 : gnutls_assert();
1494 0 : ret = tss_err(tssret);
1495 0 : goto err_sa;
1496 : }
1497 : }
1498 :
1499 3 : tssret = pTspi_Key_CreateKey(key_ctx, s.srk, 0);
1500 3 : if (tssret != 0) {
1501 0 : gnutls_assert();
1502 0 : ret = tss_err(tssret);
1503 0 : goto err_sa;
1504 : }
1505 :
1506 3 : if (flags & GNUTLS_TPM_REGISTER_KEY) {
1507 2 : TSS_UUID key_uuid;
1508 :
1509 2 : ret = randomize_uuid(&key_uuid);
1510 2 : if (ret < 0) {
1511 0 : gnutls_assert();
1512 0 : goto err_sa;
1513 : }
1514 :
1515 2 : tssret =
1516 2 : pTspi_Context_RegisterKey(s.tpm_ctx, key_ctx,
1517 : storage_type, key_uuid,
1518 : TSS_PS_TYPE_SYSTEM, srk_uuid);
1519 2 : if (tssret != 0) {
1520 0 : gnutls_assert();
1521 0 : ret = tss_err(tssret);
1522 0 : goto err_sa;
1523 : }
1524 :
1525 2 : ret =
1526 2 : encode_tpmkey_url((char **) &privkey->data, &key_uuid,
1527 : storage_type);
1528 2 : if (ret < 0) {
1529 0 : TSS_HKEY tkey;
1530 :
1531 0 : pTspi_Context_UnregisterKey(s.tpm_ctx, storage_type,
1532 : key_uuid, &tkey);
1533 0 : gnutls_assert();
1534 0 : goto err_sa;
1535 : }
1536 2 : privkey->size = strlen((char *) privkey->data);
1537 :
1538 : } else { /* get the key as blob */
1539 :
1540 :
1541 1 : tssret =
1542 1 : pTspi_GetAttribData(key_ctx, TSS_TSPATTRIB_KEY_BLOB,
1543 : TSS_TSPATTRIB_KEYBLOB_BLOB, &tint,
1544 : (void *) &tdata);
1545 1 : if (tssret != 0) {
1546 0 : gnutls_assert();
1547 0 : ret = tss_err(tssret);
1548 0 : goto err_sa;
1549 : }
1550 :
1551 :
1552 1 : if (format == GNUTLS_TPMKEY_FMT_CTK_PEM) {
1553 1 : ret =
1554 1 : _gnutls_x509_encode_string
1555 : (ASN1_ETYPE_OCTET_STRING, tdata, tint,
1556 : &tmpkey);
1557 1 : if (ret < 0) {
1558 0 : gnutls_assert();
1559 0 : goto cleanup;
1560 : }
1561 :
1562 1 : ret =
1563 2 : _gnutls_fbase64_encode("TSS KEY BLOB",
1564 1 : tmpkey.data,
1565 1 : tmpkey.size, privkey);
1566 1 : if (ret < 0) {
1567 0 : gnutls_assert();
1568 0 : goto cleanup;
1569 : }
1570 : } else {
1571 0 : UINT32 tint2;
1572 :
1573 0 : tmpkey.size = tint + 32; /* spec says no more than 20 */
1574 0 : tmpkey.data = gnutls_malloc(tmpkey.size);
1575 0 : if (tmpkey.data == NULL) {
1576 0 : gnutls_assert();
1577 0 : ret = GNUTLS_E_MEMORY_ERROR;
1578 0 : goto cleanup;
1579 : }
1580 :
1581 0 : tint2 = tmpkey.size;
1582 0 : tssret =
1583 0 : pTspi_EncodeDER_TssBlob(tint, tdata,
1584 : TSS_BLOB_TYPE_PRIVATEKEY,
1585 : &tint2, tmpkey.data);
1586 0 : if (tssret != 0) {
1587 0 : gnutls_assert();
1588 0 : ret = tss_err(tssret);
1589 0 : goto cleanup;
1590 : }
1591 :
1592 0 : tmpkey.size = tint2;
1593 :
1594 0 : privkey->data = tmpkey.data;
1595 0 : privkey->size = tmpkey.size;
1596 0 : tmpkey.data = NULL;
1597 : }
1598 : }
1599 :
1600 : /* read the public key */
1601 3 : if (pubkey != NULL) {
1602 3 : size_t psize = 0;
1603 :
1604 3 : ret = gnutls_pubkey_init(&pub);
1605 3 : if (ret < 0) {
1606 0 : gnutls_assert();
1607 0 : goto privkey_cleanup;
1608 : }
1609 :
1610 3 : ret = read_pubkey(pub, key_ctx, &psize);
1611 3 : if (ret < 0) {
1612 0 : gnutls_assert();
1613 0 : goto privkey_cleanup;
1614 : }
1615 3 : psize += 512;
1616 :
1617 3 : pubkey->data = gnutls_malloc(psize);
1618 3 : if (pubkey->data == NULL) {
1619 0 : gnutls_assert();
1620 0 : ret = GNUTLS_E_MEMORY_ERROR;
1621 0 : goto pubkey_cleanup;
1622 : }
1623 :
1624 3 : ret =
1625 3 : gnutls_pubkey_export(pub, pub_format, pubkey->data,
1626 : &psize);
1627 3 : if (ret < 0) {
1628 0 : gnutls_assert();
1629 0 : goto pubkey_cleanup;
1630 : }
1631 3 : pubkey->size = psize;
1632 :
1633 3 : gnutls_pubkey_deinit(pub);
1634 : }
1635 :
1636 3 : ret = 0;
1637 3 : goto cleanup;
1638 :
1639 0 : pubkey_cleanup:
1640 0 : gnutls_pubkey_deinit(pub);
1641 0 : privkey_cleanup:
1642 0 : gnutls_free(privkey->data);
1643 3 : cleanup:
1644 3 : gnutls_free(tmpkey.data);
1645 3 : err_sa:
1646 3 : pTspi_Context_CloseObject(s.tpm_ctx, key_ctx);
1647 3 : err_cc:
1648 3 : tpm_close_session(&s);
1649 3 : return ret;
1650 : }
1651 :
1652 :
1653 : /**
1654 : * gnutls_tpm_key_list_deinit:
1655 : * @list: a list of the keys
1656 : *
1657 : * This function will deinitialize the list of stored keys in the TPM.
1658 : *
1659 : * Since: 3.1.0
1660 : **/
1661 4 : void gnutls_tpm_key_list_deinit(gnutls_tpm_key_list_t list)
1662 : {
1663 4 : CHECK_INIT_VOID;
1664 :
1665 4 : if (list->tpm_ctx != 0)
1666 4 : pTspi_Context_Close(list->tpm_ctx);
1667 4 : gnutls_free(list);
1668 : }
1669 :
1670 : /**
1671 : * gnutls_tpm_key_list_get_url:
1672 : * @list: a list of the keys
1673 : * @idx: The index of the key (starting from zero)
1674 : * @url: The URL to be returned
1675 : * @flags: should be zero
1676 : *
1677 : * This function will return for each given index a URL of
1678 : * the corresponding key.
1679 : * If the provided index is out of bounds then %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1680 : * is returned.
1681 : *
1682 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1683 : * negative error value.
1684 : *
1685 : * Since: 3.1.0
1686 : **/
1687 : int
1688 10 : gnutls_tpm_key_list_get_url(gnutls_tpm_key_list_t list, unsigned int idx,
1689 : char **url, unsigned int flags)
1690 : {
1691 10 : CHECK_INIT;
1692 :
1693 10 : if (idx >= list->size)
1694 4 : return
1695 4 : gnutls_assert_val
1696 : (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1697 :
1698 6 : return encode_tpmkey_url(url, &list->ki[idx].keyUUID,
1699 6 : list->ki[idx].persistentStorageType);
1700 : }
1701 :
1702 : /**
1703 : * gnutls_tpm_get_registered:
1704 : * @list: a list to store the keys
1705 : *
1706 : * This function will get a list of stored keys in the TPM. The uuid
1707 : * of those keys
1708 : *
1709 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1710 : * negative error value.
1711 : *
1712 : * Since: 3.1.0
1713 : **/
1714 4 : int gnutls_tpm_get_registered(gnutls_tpm_key_list_t * list)
1715 : {
1716 4 : TSS_RESULT tssret;
1717 4 : int ret;
1718 :
1719 4 : CHECK_INIT;
1720 :
1721 4 : *list = gnutls_calloc(1, sizeof(struct tpm_key_list_st));
1722 4 : if (*list == NULL)
1723 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1724 :
1725 4 : tssret = pTspi_Context_Create(&(*list)->tpm_ctx);
1726 4 : if (tssret) {
1727 0 : gnutls_assert();
1728 0 : ret = tss_err(tssret);
1729 0 : goto cleanup;
1730 : }
1731 :
1732 4 : tssret = pTspi_Context_Connect((*list)->tpm_ctx, NULL);
1733 4 : if (tssret) {
1734 0 : gnutls_assert();
1735 0 : ret = tss_err(tssret);
1736 0 : goto cleanup;
1737 : }
1738 :
1739 4 : tssret =
1740 8 : pTspi_Context_GetRegisteredKeysByUUID2((*list)->tpm_ctx,
1741 : TSS_PS_TYPE_SYSTEM, NULL,
1742 : &(*list)->size,
1743 4 : &(*list)->ki);
1744 4 : if (tssret) {
1745 0 : gnutls_assert();
1746 0 : ret = tss_err(tssret);
1747 0 : goto cleanup;
1748 : }
1749 : return 0;
1750 :
1751 0 : cleanup:
1752 0 : gnutls_tpm_key_list_deinit(*list);
1753 :
1754 0 : return ret;
1755 : }
1756 :
1757 : /**
1758 : * gnutls_tpm_privkey_delete:
1759 : * @url: the URL describing the key
1760 : * @srk_password: a password for the SRK key
1761 : *
1762 : * This function will unregister the private key from the TPM
1763 : * chip.
1764 : *
1765 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1766 : * negative error value.
1767 : *
1768 : * Since: 3.1.0
1769 : **/
1770 2 : int gnutls_tpm_privkey_delete(const char *url, const char *srk_password)
1771 : {
1772 2 : struct tpm_ctx_st s;
1773 2 : struct tpmkey_url_st durl;
1774 2 : TSS_RESULT tssret;
1775 2 : TSS_HKEY tkey;
1776 2 : int ret;
1777 :
1778 2 : CHECK_INIT;
1779 :
1780 2 : ret = decode_tpmkey_url(url, &durl);
1781 2 : if (ret < 0)
1782 0 : return gnutls_assert_val(ret);
1783 :
1784 2 : if (durl.uuid_set == 0)
1785 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1786 :
1787 2 : ret = tpm_open_session(&s, srk_password, 1);
1788 2 : if (ret < 0)
1789 0 : return gnutls_assert_val(ret);
1790 :
1791 2 : tssret =
1792 2 : pTspi_Context_UnregisterKey(s.tpm_ctx, durl.storage, durl.uuid,
1793 : &tkey);
1794 2 : if (tssret != 0) {
1795 0 : gnutls_assert();
1796 0 : ret = tss_err(tssret);
1797 0 : goto err_cc;
1798 : }
1799 :
1800 : ret = 0;
1801 2 : err_cc:
1802 2 : tpm_close_session(&s);
1803 2 : return ret;
1804 : }
1805 : #else /* HAVE_TROUSERS */
1806 : int
1807 : gnutls_privkey_import_tpm_raw(gnutls_privkey_t pkey,
1808 : const gnutls_datum_t * fdata,
1809 : gnutls_tpmkey_fmt_t format,
1810 : const char *srk_password,
1811 : const char *key_password, unsigned int flags)
1812 : {
1813 : return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1814 : }
1815 :
1816 : int
1817 : gnutls_privkey_import_tpm_url(gnutls_privkey_t pkey,
1818 : const char *url,
1819 : const char *srk_password,
1820 : const char *key_password, unsigned int flags)
1821 : {
1822 : return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1823 : }
1824 :
1825 : int
1826 : gnutls_pubkey_import_tpm_raw(gnutls_pubkey_t pkey,
1827 : const gnutls_datum_t * fdata,
1828 : gnutls_tpmkey_fmt_t format,
1829 : const char *srk_password, unsigned int flags)
1830 : {
1831 : return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1832 : }
1833 :
1834 : int
1835 : gnutls_pubkey_import_tpm_url(gnutls_pubkey_t pkey,
1836 : const char *url,
1837 : const char *srk_password, unsigned int flags)
1838 : {
1839 : return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1840 : }
1841 :
1842 : int
1843 : gnutls_tpm_privkey_generate(gnutls_pk_algorithm_t pk, unsigned int bits,
1844 : const char *srk_password,
1845 : const char *key_password,
1846 : gnutls_tpmkey_fmt_t format,
1847 : gnutls_x509_crt_fmt_t pub_format,
1848 : gnutls_datum_t * privkey,
1849 : gnutls_datum_t * pubkey, unsigned int flags)
1850 : {
1851 : return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1852 : }
1853 :
1854 : void gnutls_tpm_key_list_deinit(gnutls_tpm_key_list_t list)
1855 : {
1856 : return;
1857 : }
1858 :
1859 : int
1860 : gnutls_tpm_key_list_get_url(gnutls_tpm_key_list_t list, unsigned int idx,
1861 : char **url, unsigned int flags)
1862 : {
1863 : return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1864 : }
1865 :
1866 : int gnutls_tpm_get_registered(gnutls_tpm_key_list_t * list)
1867 : {
1868 : return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1869 : }
1870 :
1871 : int gnutls_tpm_privkey_delete(const char *url, const char *srk_password)
1872 : {
1873 : return GNUTLS_E_UNIMPLEMENTED_FEATURE;
1874 : }
1875 : #endif /* HAVE_TROUSERS */
|